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"
14 EFI_DRIVER_BINDING_PROTOCOL gMtftp6DriverBinding
= {
15 Mtftp6DriverBindingSupported
,
16 Mtftp6DriverBindingStart
,
17 Mtftp6DriverBindingStop
,
23 EFI_SERVICE_BINDING_PROTOCOL gMtftp6ServiceBindingTemplate
= {
24 Mtftp6ServiceBindingCreateChild
,
25 Mtftp6ServiceBindingDestroyChild
30 Destroy the MTFTP6 service. The MTFTP6 service may be partly initialized,
31 or partly destroyed. If a resource is destroyed, it is marked as such in
32 case the destroy failed and is called again later.
34 @param[in] Service The MTFTP6 service to be destroyed.
38 Mtftp6DestroyService (
39 IN MTFTP6_SERVICE
*Service
43 // Make sure all children instances have been already destroyed.
45 ASSERT (Service
->ChildrenNum
== 0);
47 if (Service
->DummyUdpIo
!= NULL
) {
48 UdpIoFreeIo (Service
->DummyUdpIo
);
51 if (Service
->Timer
!= NULL
) {
52 gBS
->CloseEvent (Service
->Timer
);
60 Create then initialize a MTFTP6 service binding instance.
62 @param[in] Controller The controller to install the MTFTP6 service
64 @param[in] Image The driver binding image of the MTFTP6 driver.
65 @param[out] Service The variable to receive the created service
68 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to create the instance
69 @retval EFI_DEVICE_ERROR Failed to create a NULL UDP port to keep connection with UDP.
70 @retval EFI_SUCCESS The service instance is created for the controller.
75 IN EFI_HANDLE Controller
,
77 OUT MTFTP6_SERVICE
**Service
80 MTFTP6_SERVICE
*Mtftp6Srv
;
83 ASSERT (Service
!= NULL
);
86 Mtftp6Srv
= AllocateZeroPool (sizeof (MTFTP6_SERVICE
));
88 if (Mtftp6Srv
== NULL
) {
89 return EFI_OUT_OF_RESOURCES
;
92 Mtftp6Srv
->Signature
= MTFTP6_SERVICE_SIGNATURE
;
93 Mtftp6Srv
->Controller
= Controller
;
94 Mtftp6Srv
->Image
= Image
;
95 Mtftp6Srv
->ChildrenNum
= 0;
98 &Mtftp6Srv
->ServiceBinding
,
99 &gMtftp6ServiceBindingTemplate
,
100 sizeof (EFI_SERVICE_BINDING_PROTOCOL
)
103 InitializeListHead (&Mtftp6Srv
->Children
);
106 // Create a internal timer for all instances.
108 Status
= gBS
->CreateEvent (
109 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
116 if (EFI_ERROR (Status
)) {
117 FreePool (Mtftp6Srv
);
122 // Create a dummy Udp6Io to build parent-child relationship between Udp6 driver
123 // and Mtftp6 driver.
125 Mtftp6Srv
->DummyUdpIo
= UdpIoCreateIo (
128 Mtftp6ConfigDummyUdpIo
,
133 if (Mtftp6Srv
->DummyUdpIo
== NULL
) {
134 gBS
->CloseEvent (Mtftp6Srv
->Timer
);
135 FreePool (Mtftp6Srv
);
136 return EFI_DEVICE_ERROR
;
139 *Service
= Mtftp6Srv
;
145 Destroy the MTFTP6 instance and recycle the resources.
147 @param[in] Instance The pointer to the MTFTP6 instance.
151 Mtftp6DestroyInstance (
152 IN MTFTP6_INSTANCE
*Instance
157 MTFTP6_BLOCK_RANGE
*Block
;
159 if (Instance
->Config
!= NULL
) {
160 FreePool (Instance
->Config
);
163 if (Instance
->Token
!= NULL
&& Instance
->Token
->Event
!= NULL
) {
164 gBS
->SignalEvent (Instance
->Token
->Event
);
167 if (Instance
->LastPacket
!= NULL
) {
168 NetbufFree (Instance
->LastPacket
);
171 if (Instance
->UdpIo
!= NULL
) {
172 UdpIoFreeIo (Instance
->UdpIo
);
175 if (Instance
->McastUdpIo
!= NULL
) {
176 UdpIoFreeIo (Instance
->McastUdpIo
);
179 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Instance
->BlkList
) {
180 Block
= NET_LIST_USER_STRUCT (Entry
, MTFTP6_BLOCK_RANGE
, Link
);
181 RemoveEntryList (Entry
);
190 Create the MTFTP6 instance and initialize it.
192 @param[in] Service The pointer to the MTFTP6 service.
193 @param[out] Instance The pointer to the MTFTP6 instance.
195 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
196 @retval EFI_SUCCESS The MTFTP6 instance is created.
200 Mtftp6CreateInstance (
201 IN MTFTP6_SERVICE
*Service
,
202 OUT MTFTP6_INSTANCE
**Instance
205 MTFTP6_INSTANCE
*Mtftp6Ins
;
208 Mtftp6Ins
= AllocateZeroPool (sizeof (MTFTP6_INSTANCE
));
210 if (Mtftp6Ins
== NULL
) {
211 return EFI_OUT_OF_RESOURCES
;
214 Mtftp6Ins
->Signature
= MTFTP6_INSTANCE_SIGNATURE
;
215 Mtftp6Ins
->InDestroy
= FALSE
;
216 Mtftp6Ins
->Service
= Service
;
220 &gMtftp6ProtocolTemplate
,
221 sizeof (EFI_MTFTP6_PROTOCOL
)
224 InitializeListHead (&Mtftp6Ins
->Link
);
225 InitializeListHead (&Mtftp6Ins
->BlkList
);
227 *Instance
= Mtftp6Ins
;
234 Callback function which provided by user to remove one node in NetDestroyLinkList process.
236 @param[in] Entry The entry to be removed.
237 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
239 @retval EFI_SUCCESS The entry has been removed successfully.
240 @retval Others Fail to remove the entry.
245 Mtftp6DestroyChildEntryInHandleBuffer (
246 IN LIST_ENTRY
*Entry
,
250 MTFTP6_INSTANCE
*Instance
;
251 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
252 UINTN NumberOfChildren
;
253 EFI_HANDLE
*ChildHandleBuffer
;
255 if (Entry
== NULL
|| Context
== NULL
) {
256 return EFI_INVALID_PARAMETER
;
259 Instance
= NET_LIST_USER_STRUCT_S (Entry
, MTFTP6_INSTANCE
, Link
, MTFTP6_INSTANCE_SIGNATURE
);
260 ServiceBinding
= ((MTFTP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->ServiceBinding
;
261 NumberOfChildren
= ((MTFTP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->NumberOfChildren
;
262 ChildHandleBuffer
= ((MTFTP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->ChildHandleBuffer
;
264 if (!NetIsInHandleBuffer (Instance
->Handle
, NumberOfChildren
, ChildHandleBuffer
)) {
268 return ServiceBinding
->DestroyChild (ServiceBinding
, Instance
->Handle
);
273 This is the declaration of an EFI image entry point. This entry point is
274 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers, including
275 both device drivers and bus drivers.
277 Entry point of the MTFTP6 driver to install various protocols.
279 @param[in] ImageHandle The firmware allocated handle for the UEFI image.
280 @param[in] SystemTable The pointer to the EFI System Table.
282 @retval EFI_SUCCESS The operation completed successfully.
283 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
288 Mtftp6DriverEntryPoint (
289 IN EFI_HANDLE ImageHandle
,
290 IN EFI_SYSTEM_TABLE
*SystemTable
293 return EfiLibInstallDriverBindingComponentName2 (
296 &gMtftp6DriverBinding
,
298 &gMtftp6ComponentName
,
299 &gMtftp6ComponentName2
305 Test to see if this driver supports Controller. This service
306 is called by the EFI boot service ConnectController(). In
307 order to make drivers as small as possible, there are calling
308 restrictions for this service. ConnectController() must
309 follow these calling restrictions. If any other agent wishes to call
310 Supported(), it must also follow these calling restrictions.
312 @param[in] This Protocol instance pointer.
313 @param[in] Controller Handle of device to test
314 @param[in] RemainingDevicePath Optional parameter use to pick a specific child.
317 @retval EFI_SUCCESS This driver supports this device.
318 @retval Others This driver does not support this device.
323 Mtftp6DriverBindingSupported (
324 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
325 IN EFI_HANDLE Controller
,
326 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
329 return gBS
->OpenProtocol (
331 &gEfiUdp6ServiceBindingProtocolGuid
,
333 This
->DriverBindingHandle
,
335 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
341 Start this driver on Controller. This service is called by the
342 EFI boot service ConnectController(). In order to make
343 drivers as small as possible, there are calling restrictions for
344 this service. ConnectController() must follow these
345 calling restrictions. If any other agent wishes to call Start() it
346 must also follow these calling restrictions.
348 @param[in] This Protocol instance pointer.
349 @param[in] Controller Handle of device to bind driver to.
350 @param[in] RemainingDevicePath Optional parameter use to pick a specific child
353 @retval EFI_SUCCESS This driver is added to Controller.
354 @retval EFI_ALREADY_STARTED This driver is already running on Controller.
355 @retval Others This driver does not support this device.
360 Mtftp6DriverBindingStart (
361 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
362 IN EFI_HANDLE Controller
,
363 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
366 MTFTP6_SERVICE
*Service
;
370 // Directly return if driver is already running on this Nic handle.
372 Status
= gBS
->OpenProtocol (
374 &gEfiMtftp6ServiceBindingProtocolGuid
,
376 This
->DriverBindingHandle
,
378 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
381 if (!EFI_ERROR (Status
)) {
382 return EFI_ALREADY_STARTED
;
386 // Create Mtftp6 service for this Nic handle
388 Status
= Mtftp6CreateService (
390 This
->DriverBindingHandle
,
394 if (EFI_ERROR (Status
)) {
398 ASSERT (Service
!= NULL
);
401 // Start the internal timer to track the packet retransmission.
403 Status
= gBS
->SetTimer (
409 if (EFI_ERROR (Status
)) {
414 // Install the Mtftp6 service on the Nic handle.
416 Status
= gBS
->InstallMultipleProtocolInterfaces (
418 &gEfiMtftp6ServiceBindingProtocolGuid
,
419 &Service
->ServiceBinding
,
423 if (EFI_ERROR (Status
)) {
431 Mtftp6DestroyService (Service
);
437 Stop this driver on Controller. This service is called by the
438 EFI boot service DisconnectController(). In order to
439 make drivers as small as possible, there are calling
440 restrictions for this service. DisconnectController()
441 must follow these calling restrictions. If any other agent wishes
442 to call Stop(), it must also follow these calling restrictions.
444 @param[in] This Protocol instance pointer.
445 @param[in] Controller Handle of device to stop driver on
446 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
447 children is zero, stop the entire bus driver.
448 @param[in] ChildHandleBuffer List of Child Handles to Stop.
450 @retval EFI_SUCCESS This driver is removed Controller.
451 @retval EFI_DEVICE_ERROR An unexpected error.
452 @retval Others This driver was not removed from this device.
457 Mtftp6DriverBindingStop (
458 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
459 IN EFI_HANDLE Controller
,
460 IN UINTN NumberOfChildren
,
461 IN EFI_HANDLE
*ChildHandleBuffer
464 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
465 MTFTP6_SERVICE
*Service
;
466 EFI_HANDLE NicHandle
;
469 MTFTP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context
;
472 // Locate the Nic handle to retrieve the Mtftp6 private data.
474 NicHandle
= NetLibGetNicHandle (Controller
, &gEfiUdp6ProtocolGuid
);
476 if (NicHandle
== NULL
) {
480 Status
= gBS
->OpenProtocol (
482 &gEfiMtftp6ServiceBindingProtocolGuid
,
483 (VOID
**) &ServiceBinding
,
484 This
->DriverBindingHandle
,
486 EFI_OPEN_PROTOCOL_GET_PROTOCOL
489 if (EFI_ERROR (Status
)) {
490 return EFI_DEVICE_ERROR
;
493 Service
= MTFTP6_SERVICE_FROM_THIS (ServiceBinding
);
495 if (!IsListEmpty (&Service
->Children
)) {
497 // Destroy the Mtftp6 child instance in ChildHandleBuffer.
499 List
= &Service
->Children
;
500 Context
.ServiceBinding
= ServiceBinding
;
501 Context
.NumberOfChildren
= NumberOfChildren
;
502 Context
.ChildHandleBuffer
= ChildHandleBuffer
;
503 Status
= NetDestroyLinkList (
505 Mtftp6DestroyChildEntryInHandleBuffer
,
511 if (NumberOfChildren
== 0 && IsListEmpty (&Service
->Children
)) {
513 // Destroy the Mtftp6 service if there is no Mtftp6 child instance left.
515 gBS
->UninstallProtocolInterface (
517 &gEfiMtftp6ServiceBindingProtocolGuid
,
521 Mtftp6DestroyService (Service
);
522 Status
= EFI_SUCCESS
;
530 Creates a child handle and installs a protocol.
532 The CreateChild() function installs a protocol on ChildHandle.
533 If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
534 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
536 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
537 @param[in, out] ChildHandle Pointer to the handle of the child to create. If it is NULL,
538 then a new handle is created. If it is a pointer to an existing
539 UEFI handle, then the protocol is added to the existing UEFI handle.
541 @retval EFI_SUCCESS The protocol was added to ChildHandle.
542 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
543 @retval Others The child handle was not created.
548 Mtftp6ServiceBindingCreateChild (
549 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
550 IN OUT EFI_HANDLE
*ChildHandle
553 MTFTP6_SERVICE
*Service
;
554 MTFTP6_INSTANCE
*Instance
;
559 if (This
== NULL
|| ChildHandle
== NULL
) {
560 return EFI_INVALID_PARAMETER
;
563 Service
= MTFTP6_SERVICE_FROM_THIS (This
);
565 Status
= Mtftp6CreateInstance (Service
, &Instance
);
567 if (EFI_ERROR (Status
)) {
571 ASSERT (Instance
!= NULL
);
574 // Install the Mtftp6 protocol on the new child handle.
576 Status
= gBS
->InstallMultipleProtocolInterfaces (
578 &gEfiMtftp6ProtocolGuid
,
583 if (EFI_ERROR (Status
)) {
587 Instance
->Handle
= *ChildHandle
;
590 // Open the Udp6 protocol by child.
592 Status
= gBS
->OpenProtocol (
593 Service
->DummyUdpIo
->UdpHandle
,
594 &gEfiUdp6ProtocolGuid
,
596 gMtftp6DriverBinding
.DriverBindingHandle
,
598 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
601 if (EFI_ERROR (Status
)) {
602 gBS
->UninstallMultipleProtocolInterfaces (
604 &gEfiMtftp6ProtocolGuid
,
613 // Add the new Mtftp6 instance into the children list of Mtftp6 service.
615 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
617 InsertTailList (&Service
->Children
, &Instance
->Link
);
618 Service
->ChildrenNum
++;
620 gBS
->RestoreTPL (OldTpl
);
625 Mtftp6DestroyInstance (Instance
);
631 Destroys a child handle with a protocol installed on it.
633 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
634 that was installed by CreateChild() from ChildHandle. If the removed protocol is the
635 last protocol on ChildHandle, then ChildHandle is destroyed.
637 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
638 @param[in] ChildHandle Handle of the child to destroy.
640 @retval EFI_SUCCESS The protocol was removed from ChildHandle.
641 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
642 @retval EFI_INVALID_PARAMETER Child handle is NULL.
643 @retval Others The child handle was not destroyed
648 Mtftp6ServiceBindingDestroyChild (
649 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
650 IN EFI_HANDLE ChildHandle
653 MTFTP6_SERVICE
*Service
;
654 MTFTP6_INSTANCE
*Instance
;
655 EFI_MTFTP6_PROTOCOL
*Mtftp6
;
659 if (This
== NULL
|| ChildHandle
== NULL
) {
660 return EFI_INVALID_PARAMETER
;
664 // Locate the Nic handle to retrieve the Mtftp6 private data.
666 Status
= gBS
->OpenProtocol (
668 &gEfiMtftp6ProtocolGuid
,
670 gMtftp6DriverBinding
.DriverBindingHandle
,
672 EFI_OPEN_PROTOCOL_GET_PROTOCOL
675 if (EFI_ERROR (Status
)) {
676 return EFI_UNSUPPORTED
;
679 Instance
= MTFTP6_INSTANCE_FROM_THIS (Mtftp6
);
680 Service
= MTFTP6_SERVICE_FROM_THIS (This
);
682 if (Instance
->Service
!= Service
) {
683 return EFI_INVALID_PARAMETER
;
687 // Check whether the instance already in Destroy state.
689 if (Instance
->InDestroy
) {
693 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
695 Instance
->InDestroy
= TRUE
;
698 Service
->DummyUdpIo
->UdpHandle
,
699 &gEfiUdp6ProtocolGuid
,
700 gMtftp6DriverBinding
.DriverBindingHandle
,
704 if (Instance
->UdpIo
!= NULL
) {
706 Instance
->UdpIo
->UdpHandle
,
707 &gEfiUdp6ProtocolGuid
,
708 gMtftp6DriverBinding
.DriverBindingHandle
,
713 if (Instance
->McastUdpIo
!= NULL
) {
715 Instance
->McastUdpIo
->UdpHandle
,
716 &gEfiUdp6ProtocolGuid
,
717 gMtftp6DriverBinding
.DriverBindingHandle
,
723 // Uninstall the MTFTP6 protocol first to enable a top down destruction.
725 gBS
->RestoreTPL (OldTpl
);
726 Status
= gBS
->UninstallProtocolInterface (
728 &gEfiMtftp6ProtocolGuid
,
731 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
732 if (EFI_ERROR (Status
)) {
733 Instance
->InDestroy
= FALSE
;
734 gBS
->RestoreTPL (OldTpl
);
739 // Remove the Mtftp6 instance from the children list of Mtftp6 service.
741 RemoveEntryList (&Instance
->Link
);
742 Service
->ChildrenNum
--;
744 gBS
->RestoreTPL (OldTpl
);
746 Mtftp6DestroyInstance (Instance
);