2 Implementation of Mtftp drivers.
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "Mtftp4Impl.h"
11 EFI_DRIVER_BINDING_PROTOCOL gMtftp4DriverBinding
= {
12 Mtftp4DriverBindingSupported
,
13 Mtftp4DriverBindingStart
,
14 Mtftp4DriverBindingStop
,
20 EFI_SERVICE_BINDING_PROTOCOL gMtftp4ServiceBindingTemplete
= {
21 Mtftp4ServiceBindingCreateChild
,
22 Mtftp4ServiceBindingDestroyChild
26 The driver entry point which installs multiple protocols to the ImageHandle.
28 @param ImageHandle The MTFTP's image handle.
29 @param SystemTable The system table.
31 @retval EFI_SUCCESS The handles are successfully installed on the image.
32 @retval others some EFI_ERROR occurred.
37 Mtftp4DriverEntryPoint (
38 IN EFI_HANDLE ImageHandle
,
39 IN EFI_SYSTEM_TABLE
*SystemTable
42 return EfiLibInstallDriverBindingComponentName2 (
45 &gMtftp4DriverBinding
,
47 &gMtftp4ComponentName
,
48 &gMtftp4ComponentName2
53 Test whether MTFTP driver support this controller.
55 @param This The MTFTP driver binding instance
56 @param Controller The controller to test
57 @param RemainingDevicePath The remaining device path
59 @retval EFI_SUCCESS The controller has UDP service binding protocol
60 installed, MTFTP can support it.
61 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
62 RemainingDevicePath is already being managed by
63 the driver specified by This.
64 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
65 RemainingDevicePath is already being managed by a
66 different driver or an application that requires
68 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
69 RemainingDevicePath is not supported by the driver
75 Mtftp4DriverBindingSupported (
76 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
77 IN EFI_HANDLE Controller
,
78 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
83 Status
= gBS
->OpenProtocol (
85 &gEfiUdp4ServiceBindingProtocolGuid
,
87 This
->DriverBindingHandle
,
89 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
96 Config a NULL UDP that is used to keep the connection between UDP and MTFTP.
98 Just leave the Udp child unconfigured. When UDP is unloaded,
99 MTFTP will be informed with DriverBinding Stop.
101 @param UdpIo The UDP_IO to configure
102 @param Context The opaque parameter to the callback
104 @retval EFI_SUCCESS It always return EFI_SUCCESS directly.
109 Mtftp4ConfigNullUdp (
118 Create then initialize a MTFTP service binding instance.
120 @param Controller The controller to install the MTFTP service
122 @param Image The driver binding image of the MTFTP driver
123 @param Service The variable to receive the created service
126 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance
127 @retval EFI_DEVICE_ERROR Failed to create a NULL UDP port to keep
129 @retval EFI_SUCCESS The service instance is created for the
134 Mtftp4CreateService (
135 IN EFI_HANDLE Controller
,
137 OUT MTFTP4_SERVICE
**Service
140 MTFTP4_SERVICE
*MtftpSb
;
144 MtftpSb
= AllocatePool (sizeof (MTFTP4_SERVICE
));
146 if (MtftpSb
== NULL
) {
147 return EFI_OUT_OF_RESOURCES
;
150 MtftpSb
->Signature
= MTFTP4_SERVICE_SIGNATURE
;
151 MtftpSb
->ServiceBinding
= gMtftp4ServiceBindingTemplete
;
152 MtftpSb
->ChildrenNum
= 0;
153 InitializeListHead (&MtftpSb
->Children
);
155 MtftpSb
->Timer
= NULL
;
156 MtftpSb
->TimerNotifyLevel
= NULL
;
157 MtftpSb
->TimerToGetMap
= NULL
;
158 MtftpSb
->Controller
= Controller
;
159 MtftpSb
->Image
= Image
;
160 MtftpSb
->ConnectUdp
= NULL
;
163 // Create the timer and a udp to be notified when UDP is uninstalled
165 Status
= gBS
->CreateEvent (
166 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
172 if (EFI_ERROR (Status
)) {
177 Status
= gBS
->CreateEvent (
178 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
180 Mtftp4OnTimerTickNotifyLevel
,
182 &MtftpSb
->TimerNotifyLevel
184 if (EFI_ERROR (Status
)) {
185 gBS
->CloseEvent (MtftpSb
->Timer
);
191 // Create the timer used to time out the procedure which is used to
192 // get the default IP address.
194 Status
= gBS
->CreateEvent (
199 &MtftpSb
->TimerToGetMap
201 if (EFI_ERROR (Status
)) {
202 gBS
->CloseEvent (MtftpSb
->TimerNotifyLevel
);
203 gBS
->CloseEvent (MtftpSb
->Timer
);
208 MtftpSb
->ConnectUdp
= UdpIoCreateIo (
216 if (MtftpSb
->ConnectUdp
== NULL
) {
217 gBS
->CloseEvent (MtftpSb
->TimerToGetMap
);
218 gBS
->CloseEvent (MtftpSb
->TimerNotifyLevel
);
219 gBS
->CloseEvent (MtftpSb
->Timer
);
221 return EFI_DEVICE_ERROR
;
229 Release all the resource used the MTFTP service binding instance.
231 @param MtftpSb The MTFTP service binding instance.
236 IN MTFTP4_SERVICE
*MtftpSb
239 UdpIoFreeIo (MtftpSb
->ConnectUdp
);
240 gBS
->CloseEvent (MtftpSb
->TimerToGetMap
);
241 gBS
->CloseEvent (MtftpSb
->TimerNotifyLevel
);
242 gBS
->CloseEvent (MtftpSb
->Timer
);
246 Start the MTFTP driver on this controller.
248 MTFTP driver will install a MTFTP SERVICE BINDING protocol on the supported
249 controller, which can be used to create/destroy MTFTP children.
251 @param This The MTFTP driver binding protocol.
252 @param Controller The controller to manage.
253 @param RemainingDevicePath Remaining device path.
255 @retval EFI_ALREADY_STARTED The MTFTP service binding protocol has been
256 started on the controller.
257 @retval EFI_SUCCESS The MTFTP service binding is installed on the
263 Mtftp4DriverBindingStart (
264 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
265 IN EFI_HANDLE Controller
,
266 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
269 MTFTP4_SERVICE
*MtftpSb
;
273 // Directly return if driver is already running.
275 Status
= gBS
->OpenProtocol (
277 &gEfiMtftp4ServiceBindingProtocolGuid
,
279 This
->DriverBindingHandle
,
281 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
284 if (Status
== EFI_SUCCESS
) {
285 return EFI_ALREADY_STARTED
;
288 Status
= Mtftp4CreateService (Controller
, This
->DriverBindingHandle
, &MtftpSb
);
290 if (EFI_ERROR (Status
)) {
294 ASSERT (MtftpSb
!= NULL
);
296 Status
= gBS
->SetTimer (MtftpSb
->Timer
, TimerPeriodic
, TICKS_PER_SECOND
);
298 if (EFI_ERROR (Status
)) {
302 Status
= gBS
->SetTimer (MtftpSb
->TimerNotifyLevel
, TimerPeriodic
, TICKS_PER_SECOND
);
304 if (EFI_ERROR (Status
)) {
309 // Install the Mtftp4ServiceBinding Protocol onto Controller
311 Status
= gBS
->InstallMultipleProtocolInterfaces (
313 &gEfiMtftp4ServiceBindingProtocolGuid
,
314 &MtftpSb
->ServiceBinding
,
318 if (EFI_ERROR (Status
)) {
325 Mtftp4CleanService (MtftpSb
);
332 Callback function which provided by user to remove one node in NetDestroyLinkList process.
334 @param[in] Entry The entry to be removed.
335 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
337 @retval EFI_SUCCESS The entry has been removed successfully.
338 @retval Others Fail to remove the entry.
343 Mtftp4DestroyChildEntryInHandleBuffer (
344 IN LIST_ENTRY
*Entry
,
348 MTFTP4_PROTOCOL
*Instance
;
349 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
350 UINTN NumberOfChildren
;
351 EFI_HANDLE
*ChildHandleBuffer
;
353 if ((Entry
== NULL
) || (Context
== NULL
)) {
354 return EFI_INVALID_PARAMETER
;
357 Instance
= NET_LIST_USER_STRUCT_S (Entry
, MTFTP4_PROTOCOL
, Link
, MTFTP4_PROTOCOL_SIGNATURE
);
358 ServiceBinding
= ((MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*)Context
)->ServiceBinding
;
359 NumberOfChildren
= ((MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*)Context
)->NumberOfChildren
;
360 ChildHandleBuffer
= ((MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*)Context
)->ChildHandleBuffer
;
362 if (!NetIsInHandleBuffer (Instance
->Handle
, NumberOfChildren
, ChildHandleBuffer
)) {
366 return ServiceBinding
->DestroyChild (ServiceBinding
, Instance
->Handle
);
370 Stop the MTFTP driver on controller. The controller is a UDP
373 @param This The MTFTP driver binding protocol
374 @param Controller The controller to stop
375 @param NumberOfChildren The number of children
376 @param ChildHandleBuffer The array of the child handle.
378 @retval EFI_SUCCESS The driver is stopped on the controller.
379 @retval EFI_DEVICE_ERROR Failed to stop the driver on the controller.
384 Mtftp4DriverBindingStop (
385 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
386 IN EFI_HANDLE Controller
,
387 IN UINTN NumberOfChildren
,
388 IN EFI_HANDLE
*ChildHandleBuffer
391 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
392 MTFTP4_SERVICE
*MtftpSb
;
393 EFI_HANDLE NicHandle
;
396 MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context
;
399 // MTFTP driver opens UDP child, So, Controller is a UDP
400 // child handle. Locate the Nic handle first. Then get the
401 // MTFTP private data back.
403 NicHandle
= NetLibGetNicHandle (Controller
, &gEfiUdp4ProtocolGuid
);
405 if (NicHandle
== NULL
) {
409 Status
= gBS
->OpenProtocol (
411 &gEfiMtftp4ServiceBindingProtocolGuid
,
412 (VOID
**)&ServiceBinding
,
413 This
->DriverBindingHandle
,
415 EFI_OPEN_PROTOCOL_GET_PROTOCOL
418 if (EFI_ERROR (Status
)) {
419 return EFI_DEVICE_ERROR
;
422 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (ServiceBinding
);
424 if (!IsListEmpty (&MtftpSb
->Children
)) {
426 // Destroy the Mtftp4 child instance in ChildHandleBuffer.
428 List
= &MtftpSb
->Children
;
429 Context
.ServiceBinding
= ServiceBinding
;
430 Context
.NumberOfChildren
= NumberOfChildren
;
431 Context
.ChildHandleBuffer
= ChildHandleBuffer
;
432 Status
= NetDestroyLinkList (
434 Mtftp4DestroyChildEntryInHandleBuffer
,
440 if ((NumberOfChildren
== 0) && IsListEmpty (&MtftpSb
->Children
)) {
441 gBS
->UninstallProtocolInterface (
443 &gEfiMtftp4ServiceBindingProtocolGuid
,
447 Mtftp4CleanService (MtftpSb
);
448 if (gMtftp4ControllerNameTable
!= NULL
) {
449 FreeUnicodeStringTable (gMtftp4ControllerNameTable
);
450 gMtftp4ControllerNameTable
= NULL
;
455 Status
= EFI_SUCCESS
;
462 Initialize a MTFTP protocol instance which is the child of MtftpSb.
464 @param MtftpSb The MTFTP service binding protocol.
465 @param Instance The MTFTP instance to initialize.
470 IN MTFTP4_SERVICE
*MtftpSb
,
471 OUT MTFTP4_PROTOCOL
*Instance
474 ZeroMem (Instance
, sizeof (MTFTP4_PROTOCOL
));
476 Instance
->Signature
= MTFTP4_PROTOCOL_SIGNATURE
;
477 InitializeListHead (&Instance
->Link
);
478 CopyMem (&Instance
->Mtftp4
, &gMtftp4ProtocolTemplate
, sizeof (Instance
->Mtftp4
));
479 Instance
->State
= MTFTP4_STATE_UNCONFIGED
;
480 Instance
->Service
= MtftpSb
;
482 InitializeListHead (&Instance
->Blocks
);
486 Create a MTFTP child for the service binding instance, then
487 install the MTFTP protocol to the ChildHandle.
489 @param This The MTFTP service binding instance.
490 @param ChildHandle The Child handle to install the MTFTP protocol.
492 @retval EFI_INVALID_PARAMETER The parameter is invalid.
493 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the new child.
494 @retval EFI_SUCCESS The child is successfully create.
499 Mtftp4ServiceBindingCreateChild (
500 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
501 IN EFI_HANDLE
*ChildHandle
504 MTFTP4_SERVICE
*MtftpSb
;
505 MTFTP4_PROTOCOL
*Instance
;
510 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
511 return EFI_INVALID_PARAMETER
;
514 Instance
= AllocatePool (sizeof (*Instance
));
516 if (Instance
== NULL
) {
517 return EFI_OUT_OF_RESOURCES
;
520 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (This
);
522 Mtftp4InitProtocol (MtftpSb
, Instance
);
524 Instance
->UnicastPort
= UdpIoCreateIo (
532 if (Instance
->UnicastPort
== NULL
) {
534 return EFI_OUT_OF_RESOURCES
;
538 // Install the MTFTP protocol onto ChildHandle
540 Status
= gBS
->InstallMultipleProtocolInterfaces (
542 &gEfiMtftp4ProtocolGuid
,
547 if (EFI_ERROR (Status
)) {
548 UdpIoFreeIo (Instance
->UnicastPort
);
553 Instance
->Handle
= *ChildHandle
;
556 // Open the Udp4 protocol BY_CHILD.
558 Status
= gBS
->OpenProtocol (
559 MtftpSb
->ConnectUdp
->UdpHandle
,
560 &gEfiUdp4ProtocolGuid
,
562 gMtftp4DriverBinding
.DriverBindingHandle
,
564 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
566 if (EFI_ERROR (Status
)) {
571 // Open the Udp4 protocol by child.
573 Status
= gBS
->OpenProtocol (
574 Instance
->UnicastPort
->UdpHandle
,
575 &gEfiUdp4ProtocolGuid
,
577 gMtftp4DriverBinding
.DriverBindingHandle
,
579 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
581 if (EFI_ERROR (Status
)) {
583 // Close the Udp4 protocol.
586 MtftpSb
->ConnectUdp
->UdpHandle
,
587 &gEfiUdp4ProtocolGuid
,
588 gMtftp4DriverBinding
.DriverBindingHandle
,
595 // Add it to the parent's child list.
597 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
599 InsertTailList (&MtftpSb
->Children
, &Instance
->Link
);
600 MtftpSb
->ChildrenNum
++;
602 gBS
->RestoreTPL (OldTpl
);
607 if (Instance
->Handle
!= NULL
) {
608 gBS
->UninstallMultipleProtocolInterfaces (
610 &gEfiMtftp4ProtocolGuid
,
616 UdpIoFreeIo (Instance
->UnicastPort
);
623 Destroy one of the service binding's child.
625 @param This The service binding instance
626 @param ChildHandle The child handle to destroy
628 @retval EFI_INVALID_PARAMETER The parameter is invalid.
629 @retval EFI_UNSUPPORTED The child may have already been destroyed.
630 @retval EFI_SUCCESS The child is destroyed and removed from the
636 Mtftp4ServiceBindingDestroyChild (
637 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
638 IN EFI_HANDLE ChildHandle
641 MTFTP4_SERVICE
*MtftpSb
;
642 MTFTP4_PROTOCOL
*Instance
;
643 EFI_MTFTP4_PROTOCOL
*Mtftp4
;
647 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
648 return EFI_INVALID_PARAMETER
;
652 // Retrieve the private context data structures
654 Status
= gBS
->OpenProtocol (
656 &gEfiMtftp4ProtocolGuid
,
658 gMtftp4DriverBinding
.DriverBindingHandle
,
660 EFI_OPEN_PROTOCOL_GET_PROTOCOL
663 if (EFI_ERROR (Status
)) {
664 return EFI_UNSUPPORTED
;
667 Instance
= MTFTP4_PROTOCOL_FROM_THIS (Mtftp4
);
668 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (This
);
670 if (Instance
->Service
!= MtftpSb
) {
671 return EFI_INVALID_PARAMETER
;
674 if (Instance
->InDestroy
) {
678 Instance
->InDestroy
= TRUE
;
681 // Close the Udp4 protocol.
684 MtftpSb
->ConnectUdp
->UdpHandle
,
685 &gEfiUdp4ProtocolGuid
,
686 gMtftp4DriverBinding
.DriverBindingHandle
,
691 Instance
->UnicastPort
->UdpHandle
,
692 &gEfiUdp4ProtocolGuid
,
693 gMtftp4DriverBinding
.DriverBindingHandle
,
697 if (Instance
->McastUdpPort
!= NULL
) {
699 Instance
->McastUdpPort
->UdpHandle
,
700 &gEfiUdp4ProtocolGuid
,
701 gMtftp4DriverBinding
.DriverBindingHandle
,
707 // Uninstall the MTFTP4 protocol first to enable a top down destruction.
709 Status
= gBS
->UninstallProtocolInterface (
711 &gEfiMtftp4ProtocolGuid
,
715 if (EFI_ERROR (Status
)) {
716 Instance
->InDestroy
= FALSE
;
720 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
722 Mtftp4CleanOperation (Instance
, EFI_DEVICE_ERROR
);
723 UdpIoFreeIo (Instance
->UnicastPort
);
725 RemoveEntryList (&Instance
->Link
);
726 MtftpSb
->ChildrenNum
--;
728 gBS
->RestoreTPL (OldTpl
);