2 Driver Binding functions and Service Binding functions
3 implementation for Mtftp6 Driver.
5 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include "Mtftp6Impl.h"
13 EFI_DRIVER_BINDING_PROTOCOL gMtftp6DriverBinding
= {
14 Mtftp6DriverBindingSupported
,
15 Mtftp6DriverBindingStart
,
16 Mtftp6DriverBindingStop
,
22 EFI_SERVICE_BINDING_PROTOCOL gMtftp6ServiceBindingTemplate
= {
23 Mtftp6ServiceBindingCreateChild
,
24 Mtftp6ServiceBindingDestroyChild
28 Destroy the MTFTP6 service. The MTFTP6 service may be partly initialized,
29 or partly destroyed. If a resource is destroyed, it is marked as such in
30 case the destroy failed and is called again later.
32 @param[in] Service The MTFTP6 service to be destroyed.
36 Mtftp6DestroyService (
37 IN MTFTP6_SERVICE
*Service
41 // Make sure all children instances have been already destroyed.
43 ASSERT (Service
->ChildrenNum
== 0);
45 if (Service
->DummyUdpIo
!= NULL
) {
46 UdpIoFreeIo (Service
->DummyUdpIo
);
49 if (Service
->Timer
!= NULL
) {
50 gBS
->CloseEvent (Service
->Timer
);
57 Create then initialize a MTFTP6 service binding instance.
59 @param[in] Controller The controller to install the MTFTP6 service
61 @param[in] Image The driver binding image of the MTFTP6 driver.
62 @param[out] Service The variable to receive the created service
65 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to create the instance
66 @retval EFI_DEVICE_ERROR Failed to create a NULL UDP port to keep connection with UDP.
67 @retval EFI_SUCCESS The service instance is created for the controller.
72 IN EFI_HANDLE Controller
,
74 OUT MTFTP6_SERVICE
**Service
77 MTFTP6_SERVICE
*Mtftp6Srv
;
80 ASSERT (Service
!= NULL
);
83 Mtftp6Srv
= AllocateZeroPool (sizeof (MTFTP6_SERVICE
));
85 if (Mtftp6Srv
== NULL
) {
86 return EFI_OUT_OF_RESOURCES
;
89 Mtftp6Srv
->Signature
= MTFTP6_SERVICE_SIGNATURE
;
90 Mtftp6Srv
->Controller
= Controller
;
91 Mtftp6Srv
->Image
= Image
;
92 Mtftp6Srv
->ChildrenNum
= 0;
95 &Mtftp6Srv
->ServiceBinding
,
96 &gMtftp6ServiceBindingTemplate
,
97 sizeof (EFI_SERVICE_BINDING_PROTOCOL
)
100 InitializeListHead (&Mtftp6Srv
->Children
);
103 // Create a internal timer for all instances.
105 Status
= gBS
->CreateEvent (
106 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
113 if (EFI_ERROR (Status
)) {
114 FreePool (Mtftp6Srv
);
119 // Create a dummy Udp6Io to build parent-child relationship between Udp6 driver
120 // and Mtftp6 driver.
122 Mtftp6Srv
->DummyUdpIo
= UdpIoCreateIo (
125 Mtftp6ConfigDummyUdpIo
,
130 if (Mtftp6Srv
->DummyUdpIo
== NULL
) {
131 gBS
->CloseEvent (Mtftp6Srv
->Timer
);
132 FreePool (Mtftp6Srv
);
133 return EFI_DEVICE_ERROR
;
136 *Service
= Mtftp6Srv
;
141 Destroy the MTFTP6 instance and recycle the resources.
143 @param[in] Instance The pointer to the MTFTP6 instance.
147 Mtftp6DestroyInstance (
148 IN MTFTP6_INSTANCE
*Instance
153 MTFTP6_BLOCK_RANGE
*Block
;
155 if (Instance
->Config
!= NULL
) {
156 FreePool (Instance
->Config
);
159 if ((Instance
->Token
!= NULL
) && (Instance
->Token
->Event
!= NULL
)) {
160 gBS
->SignalEvent (Instance
->Token
->Event
);
163 if (Instance
->LastPacket
!= NULL
) {
164 NetbufFree (Instance
->LastPacket
);
167 if (Instance
->UdpIo
!= NULL
) {
168 UdpIoFreeIo (Instance
->UdpIo
);
171 if (Instance
->McastUdpIo
!= NULL
) {
172 UdpIoFreeIo (Instance
->McastUdpIo
);
175 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Instance
->BlkList
) {
176 Block
= NET_LIST_USER_STRUCT (Entry
, MTFTP6_BLOCK_RANGE
, Link
);
177 RemoveEntryList (Entry
);
185 Create the MTFTP6 instance and initialize it.
187 @param[in] Service The pointer to the MTFTP6 service.
188 @param[out] Instance The pointer to the MTFTP6 instance.
190 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
191 @retval EFI_SUCCESS The MTFTP6 instance is created.
195 Mtftp6CreateInstance (
196 IN MTFTP6_SERVICE
*Service
,
197 OUT MTFTP6_INSTANCE
**Instance
200 MTFTP6_INSTANCE
*Mtftp6Ins
;
203 Mtftp6Ins
= AllocateZeroPool (sizeof (MTFTP6_INSTANCE
));
205 if (Mtftp6Ins
== NULL
) {
206 return EFI_OUT_OF_RESOURCES
;
209 Mtftp6Ins
->Signature
= MTFTP6_INSTANCE_SIGNATURE
;
210 Mtftp6Ins
->InDestroy
= FALSE
;
211 Mtftp6Ins
->Service
= Service
;
215 &gMtftp6ProtocolTemplate
,
216 sizeof (EFI_MTFTP6_PROTOCOL
)
219 InitializeListHead (&Mtftp6Ins
->Link
);
220 InitializeListHead (&Mtftp6Ins
->BlkList
);
222 *Instance
= Mtftp6Ins
;
228 Callback function which provided by user to remove one node in NetDestroyLinkList process.
230 @param[in] Entry The entry to be removed.
231 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
233 @retval EFI_SUCCESS The entry has been removed successfully.
234 @retval Others Fail to remove the entry.
239 Mtftp6DestroyChildEntryInHandleBuffer (
240 IN LIST_ENTRY
*Entry
,
244 MTFTP6_INSTANCE
*Instance
;
245 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
246 UINTN NumberOfChildren
;
247 EFI_HANDLE
*ChildHandleBuffer
;
249 if ((Entry
== NULL
) || (Context
== NULL
)) {
250 return EFI_INVALID_PARAMETER
;
253 Instance
= NET_LIST_USER_STRUCT_S (Entry
, MTFTP6_INSTANCE
, Link
, MTFTP6_INSTANCE_SIGNATURE
);
254 ServiceBinding
= ((MTFTP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*)Context
)->ServiceBinding
;
255 NumberOfChildren
= ((MTFTP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*)Context
)->NumberOfChildren
;
256 ChildHandleBuffer
= ((MTFTP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*)Context
)->ChildHandleBuffer
;
258 if (!NetIsInHandleBuffer (Instance
->Handle
, NumberOfChildren
, ChildHandleBuffer
)) {
262 return ServiceBinding
->DestroyChild (ServiceBinding
, Instance
->Handle
);
266 This is the declaration of an EFI image entry point. This entry point is
267 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers, including
268 both device drivers and bus drivers.
270 Entry point of the MTFTP6 driver to install various protocols.
272 @param[in] ImageHandle The firmware allocated handle for the UEFI image.
273 @param[in] SystemTable The pointer to the EFI System Table.
275 @retval EFI_SUCCESS The operation completed successfully.
276 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
281 Mtftp6DriverEntryPoint (
282 IN EFI_HANDLE ImageHandle
,
283 IN EFI_SYSTEM_TABLE
*SystemTable
286 return EfiLibInstallDriverBindingComponentName2 (
289 &gMtftp6DriverBinding
,
291 &gMtftp6ComponentName
,
292 &gMtftp6ComponentName2
297 Test to see if this driver supports Controller. This service
298 is called by the EFI boot service ConnectController(). In
299 order to make drivers as small as possible, there are calling
300 restrictions for this service. ConnectController() must
301 follow these calling restrictions. If any other agent wishes to call
302 Supported(), it must also follow these calling restrictions.
304 @param[in] This Protocol instance pointer.
305 @param[in] Controller Handle of device to test
306 @param[in] RemainingDevicePath Optional parameter use to pick a specific child.
309 @retval EFI_SUCCESS This driver supports this device.
310 @retval Others This driver does not support this device.
315 Mtftp6DriverBindingSupported (
316 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
317 IN EFI_HANDLE Controller
,
318 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
321 return gBS
->OpenProtocol (
323 &gEfiUdp6ServiceBindingProtocolGuid
,
325 This
->DriverBindingHandle
,
327 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
332 Start this driver on Controller. This service is called by the
333 EFI boot service ConnectController(). In order to make
334 drivers as small as possible, there are calling restrictions for
335 this service. ConnectController() must follow these
336 calling restrictions. If any other agent wishes to call Start() it
337 must also follow these calling restrictions.
339 @param[in] This Protocol instance pointer.
340 @param[in] Controller Handle of device to bind driver to.
341 @param[in] RemainingDevicePath Optional parameter use to pick a specific child
344 @retval EFI_SUCCESS This driver is added to Controller.
345 @retval EFI_ALREADY_STARTED This driver is already running on Controller.
346 @retval Others This driver does not support this device.
351 Mtftp6DriverBindingStart (
352 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
353 IN EFI_HANDLE Controller
,
354 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
357 MTFTP6_SERVICE
*Service
;
361 // Directly return if driver is already running on this Nic handle.
363 Status
= gBS
->OpenProtocol (
365 &gEfiMtftp6ServiceBindingProtocolGuid
,
367 This
->DriverBindingHandle
,
369 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
372 if (!EFI_ERROR (Status
)) {
373 return EFI_ALREADY_STARTED
;
377 // Create Mtftp6 service for this Nic handle
379 Status
= Mtftp6CreateService (
381 This
->DriverBindingHandle
,
385 if (EFI_ERROR (Status
)) {
389 ASSERT (Service
!= NULL
);
392 // Start the internal timer to track the packet retransmission.
394 Status
= gBS
->SetTimer (
400 if (EFI_ERROR (Status
)) {
405 // Install the Mtftp6 service on the Nic handle.
407 Status
= gBS
->InstallMultipleProtocolInterfaces (
409 &gEfiMtftp6ServiceBindingProtocolGuid
,
410 &Service
->ServiceBinding
,
414 if (EFI_ERROR (Status
)) {
422 Mtftp6DestroyService (Service
);
427 Stop this driver on Controller. This service is called by the
428 EFI boot service DisconnectController(). In order to
429 make drivers as small as possible, there are calling
430 restrictions for this service. DisconnectController()
431 must follow these calling restrictions. If any other agent wishes
432 to call Stop(), it must also follow these calling restrictions.
434 @param[in] This Protocol instance pointer.
435 @param[in] Controller Handle of device to stop driver on
436 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
437 children is zero, stop the entire bus driver.
438 @param[in] ChildHandleBuffer List of Child Handles to Stop.
440 @retval EFI_SUCCESS This driver is removed Controller.
441 @retval EFI_DEVICE_ERROR An unexpected error.
442 @retval Others This driver was not removed from this device.
447 Mtftp6DriverBindingStop (
448 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
449 IN EFI_HANDLE Controller
,
450 IN UINTN NumberOfChildren
,
451 IN EFI_HANDLE
*ChildHandleBuffer
454 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
455 MTFTP6_SERVICE
*Service
;
456 EFI_HANDLE NicHandle
;
459 MTFTP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context
;
462 // Locate the Nic handle to retrieve the Mtftp6 private data.
464 NicHandle
= NetLibGetNicHandle (Controller
, &gEfiUdp6ProtocolGuid
);
466 if (NicHandle
== NULL
) {
470 Status
= gBS
->OpenProtocol (
472 &gEfiMtftp6ServiceBindingProtocolGuid
,
473 (VOID
**)&ServiceBinding
,
474 This
->DriverBindingHandle
,
476 EFI_OPEN_PROTOCOL_GET_PROTOCOL
479 if (EFI_ERROR (Status
)) {
480 return EFI_DEVICE_ERROR
;
483 Service
= MTFTP6_SERVICE_FROM_THIS (ServiceBinding
);
485 if (!IsListEmpty (&Service
->Children
)) {
487 // Destroy the Mtftp6 child instance in ChildHandleBuffer.
489 List
= &Service
->Children
;
490 Context
.ServiceBinding
= ServiceBinding
;
491 Context
.NumberOfChildren
= NumberOfChildren
;
492 Context
.ChildHandleBuffer
= ChildHandleBuffer
;
493 Status
= NetDestroyLinkList (
495 Mtftp6DestroyChildEntryInHandleBuffer
,
501 if ((NumberOfChildren
== 0) && IsListEmpty (&Service
->Children
)) {
503 // Destroy the Mtftp6 service if there is no Mtftp6 child instance left.
505 gBS
->UninstallProtocolInterface (
507 &gEfiMtftp6ServiceBindingProtocolGuid
,
511 Mtftp6DestroyService (Service
);
512 Status
= EFI_SUCCESS
;
519 Creates a child handle and installs a protocol.
521 The CreateChild() function installs a protocol on ChildHandle.
522 If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
523 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
525 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
526 @param[in, out] ChildHandle Pointer to the handle of the child to create. If it is NULL,
527 then a new handle is created. If it is a pointer to an existing
528 UEFI handle, then the protocol is added to the existing UEFI handle.
530 @retval EFI_SUCCESS The protocol was added to ChildHandle.
531 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
532 @retval Others The child handle was not created.
537 Mtftp6ServiceBindingCreateChild (
538 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
539 IN OUT EFI_HANDLE
*ChildHandle
542 MTFTP6_SERVICE
*Service
;
543 MTFTP6_INSTANCE
*Instance
;
548 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
549 return EFI_INVALID_PARAMETER
;
552 Service
= MTFTP6_SERVICE_FROM_THIS (This
);
554 Status
= Mtftp6CreateInstance (Service
, &Instance
);
556 if (EFI_ERROR (Status
)) {
560 ASSERT (Instance
!= NULL
);
563 // Install the Mtftp6 protocol on the new child handle.
565 Status
= gBS
->InstallMultipleProtocolInterfaces (
567 &gEfiMtftp6ProtocolGuid
,
572 if (EFI_ERROR (Status
)) {
576 Instance
->Handle
= *ChildHandle
;
579 // Open the Udp6 protocol by child.
581 Status
= gBS
->OpenProtocol (
582 Service
->DummyUdpIo
->UdpHandle
,
583 &gEfiUdp6ProtocolGuid
,
585 gMtftp6DriverBinding
.DriverBindingHandle
,
587 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
590 if (EFI_ERROR (Status
)) {
591 gBS
->UninstallMultipleProtocolInterfaces (
593 &gEfiMtftp6ProtocolGuid
,
602 // Add the new Mtftp6 instance into the children list of Mtftp6 service.
604 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
606 InsertTailList (&Service
->Children
, &Instance
->Link
);
607 Service
->ChildrenNum
++;
609 gBS
->RestoreTPL (OldTpl
);
614 Mtftp6DestroyInstance (Instance
);
619 Destroys a child handle with a protocol installed on it.
621 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
622 that was installed by CreateChild() from ChildHandle. If the removed protocol is the
623 last protocol on ChildHandle, then ChildHandle is destroyed.
625 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
626 @param[in] ChildHandle Handle of the child to destroy.
628 @retval EFI_SUCCESS The protocol was removed from ChildHandle.
629 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
630 @retval EFI_INVALID_PARAMETER Child handle is NULL.
631 @retval Others The child handle was not destroyed
636 Mtftp6ServiceBindingDestroyChild (
637 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
638 IN EFI_HANDLE ChildHandle
641 MTFTP6_SERVICE
*Service
;
642 MTFTP6_INSTANCE
*Instance
;
643 EFI_MTFTP6_PROTOCOL
*Mtftp6
;
647 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
648 return EFI_INVALID_PARAMETER
;
652 // Locate the Nic handle to retrieve the Mtftp6 private data.
654 Status
= gBS
->OpenProtocol (
656 &gEfiMtftp6ProtocolGuid
,
658 gMtftp6DriverBinding
.DriverBindingHandle
,
660 EFI_OPEN_PROTOCOL_GET_PROTOCOL
663 if (EFI_ERROR (Status
)) {
664 return EFI_UNSUPPORTED
;
667 Instance
= MTFTP6_INSTANCE_FROM_THIS (Mtftp6
);
668 Service
= MTFTP6_SERVICE_FROM_THIS (This
);
670 if (Instance
->Service
!= Service
) {
671 return EFI_INVALID_PARAMETER
;
675 // Check whether the instance already in Destroy state.
677 if (Instance
->InDestroy
) {
681 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
683 Instance
->InDestroy
= TRUE
;
686 Service
->DummyUdpIo
->UdpHandle
,
687 &gEfiUdp6ProtocolGuid
,
688 gMtftp6DriverBinding
.DriverBindingHandle
,
692 if (Instance
->UdpIo
!= NULL
) {
694 Instance
->UdpIo
->UdpHandle
,
695 &gEfiUdp6ProtocolGuid
,
696 gMtftp6DriverBinding
.DriverBindingHandle
,
701 if (Instance
->McastUdpIo
!= NULL
) {
703 Instance
->McastUdpIo
->UdpHandle
,
704 &gEfiUdp6ProtocolGuid
,
705 gMtftp6DriverBinding
.DriverBindingHandle
,
711 // Uninstall the MTFTP6 protocol first to enable a top down destruction.
713 gBS
->RestoreTPL (OldTpl
);
714 Status
= gBS
->UninstallProtocolInterface (
716 &gEfiMtftp6ProtocolGuid
,
719 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
720 if (EFI_ERROR (Status
)) {
721 Instance
->InDestroy
= FALSE
;
722 gBS
->RestoreTPL (OldTpl
);
727 // Remove the Mtftp6 instance from the children list of Mtftp6 service.
729 RemoveEntryList (&Instance
->Link
);
730 Service
->ChildrenNum
--;
732 gBS
->RestoreTPL (OldTpl
);
734 Mtftp6DestroyInstance (Instance
);