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
27 The driver entry point which installs multiple protocols to the ImageHandle.
29 @param ImageHandle The MTFTP's image handle.
30 @param SystemTable The system table.
32 @retval EFI_SUCCESS The handles are successfully installed on the image.
33 @retval others some EFI_ERROR occured.
38 Mtftp4DriverEntryPoint (
39 IN EFI_HANDLE ImageHandle
,
40 IN EFI_SYSTEM_TABLE
*SystemTable
43 return EfiLibInstallDriverBindingComponentName2 (
46 &gMtftp4DriverBinding
,
48 &gMtftp4ComponentName
,
49 &gMtftp4ComponentName2
55 Test whether MTFTP driver support this controller.
57 @param This The MTFTP driver binding instance
58 @param Controller The controller to test
59 @param RemainingDevicePath The remaining device path
61 @retval EFI_SUCCESS The controller has UDP service binding protocol
62 installed, MTFTP can support it.
63 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
64 RemainingDevicePath is already being managed by
65 the driver specified by This.
66 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
67 RemainingDevicePath is already being managed by a
68 different driver or an application that requires
70 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
71 RemainingDevicePath is not supported by the driver
77 Mtftp4DriverBindingSupported (
78 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
79 IN EFI_HANDLE Controller
,
80 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
85 Status
= gBS
->OpenProtocol (
87 &gEfiUdp4ServiceBindingProtocolGuid
,
89 This
->DriverBindingHandle
,
91 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
99 Config a NULL UDP that is used to keep the connection between UDP and MTFTP.
101 Just leave the Udp child unconfigured. When UDP is unloaded,
102 MTFTP will be informed with DriverBinding Stop.
104 @param UdpIo The UDP_IO to configure
105 @param Context The opaque parameter to the callback
107 @retval EFI_SUCCESS It always return EFI_SUCCESS directly.
112 Mtftp4ConfigNullUdp (
122 Create then initialize a MTFTP service binding instance.
124 @param Controller The controller to install the MTFTP service
126 @param Image The driver binding image of the MTFTP driver
127 @param Service The variable to receive the created service
130 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance
131 @retval EFI_DEVICE_ERROR Failed to create a NULL UDP port to keep
133 @retval EFI_SUCCESS The service instance is created for the
138 Mtftp4CreateService (
139 IN EFI_HANDLE Controller
,
141 OUT MTFTP4_SERVICE
**Service
144 MTFTP4_SERVICE
*MtftpSb
;
148 MtftpSb
= AllocatePool (sizeof (MTFTP4_SERVICE
));
150 if (MtftpSb
== NULL
) {
151 return EFI_OUT_OF_RESOURCES
;
154 MtftpSb
->Signature
= MTFTP4_SERVICE_SIGNATURE
;
155 MtftpSb
->ServiceBinding
= gMtftp4ServiceBindingTemplete
;
156 MtftpSb
->ChildrenNum
= 0;
157 InitializeListHead (&MtftpSb
->Children
);
159 MtftpSb
->Timer
= NULL
;
160 MtftpSb
->TimerNotifyLevel
= NULL
;
161 MtftpSb
->TimerToGetMap
= NULL
;
162 MtftpSb
->Controller
= Controller
;
163 MtftpSb
->Image
= Image
;
164 MtftpSb
->ConnectUdp
= NULL
;
167 // Create the timer and a udp to be notified when UDP is uninstalled
169 Status
= gBS
->CreateEvent (
170 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
176 if (EFI_ERROR (Status
)) {
181 Status
= gBS
->CreateEvent (
182 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
184 Mtftp4OnTimerTickNotifyLevel
,
186 &MtftpSb
->TimerNotifyLevel
188 if (EFI_ERROR (Status
)) {
189 gBS
->CloseEvent (MtftpSb
->Timer
);
195 // Create the timer used to time out the procedure which is used to
196 // get the default IP address.
198 Status
= gBS
->CreateEvent (
203 &MtftpSb
->TimerToGetMap
205 if (EFI_ERROR (Status
)) {
206 gBS
->CloseEvent (MtftpSb
->TimerNotifyLevel
);
207 gBS
->CloseEvent (MtftpSb
->Timer
);
212 MtftpSb
->ConnectUdp
= UdpIoCreateIo (
220 if (MtftpSb
->ConnectUdp
== NULL
) {
221 gBS
->CloseEvent (MtftpSb
->TimerToGetMap
);
222 gBS
->CloseEvent (MtftpSb
->TimerNotifyLevel
);
223 gBS
->CloseEvent (MtftpSb
->Timer
);
225 return EFI_DEVICE_ERROR
;
234 Release all the resource used the MTFTP service binding instance.
236 @param MtftpSb The MTFTP service binding instance.
241 IN MTFTP4_SERVICE
*MtftpSb
244 UdpIoFreeIo (MtftpSb
->ConnectUdp
);
245 gBS
->CloseEvent (MtftpSb
->TimerToGetMap
);
246 gBS
->CloseEvent (MtftpSb
->TimerNotifyLevel
);
247 gBS
->CloseEvent (MtftpSb
->Timer
);
252 Start the MTFTP driver on this controller.
254 MTFTP driver will install a MTFTP SERVICE BINDING protocol on the supported
255 controller, which can be used to create/destroy MTFTP children.
257 @param This The MTFTP driver binding protocol.
258 @param Controller The controller to manage.
259 @param RemainingDevicePath Remaining device path.
261 @retval EFI_ALREADY_STARTED The MTFTP service binding protocol has been
262 started on the controller.
263 @retval EFI_SUCCESS The MTFTP service binding is installed on the
269 Mtftp4DriverBindingStart (
270 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
271 IN EFI_HANDLE Controller
,
272 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
275 MTFTP4_SERVICE
*MtftpSb
;
279 // Directly return if driver is already running.
281 Status
= gBS
->OpenProtocol (
283 &gEfiMtftp4ServiceBindingProtocolGuid
,
285 This
->DriverBindingHandle
,
287 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
290 if (Status
== EFI_SUCCESS
) {
291 return EFI_ALREADY_STARTED
;
294 Status
= Mtftp4CreateService (Controller
, This
->DriverBindingHandle
, &MtftpSb
);
296 if (EFI_ERROR (Status
)) {
299 ASSERT (MtftpSb
!= NULL
);
301 Status
= gBS
->SetTimer (MtftpSb
->Timer
, TimerPeriodic
, TICKS_PER_SECOND
);
303 if (EFI_ERROR (Status
)) {
307 Status
= gBS
->SetTimer (MtftpSb
->TimerNotifyLevel
, TimerPeriodic
, TICKS_PER_SECOND
);
309 if (EFI_ERROR (Status
)) {
314 // Install the Mtftp4ServiceBinding Protocol onto Controller
316 Status
= gBS
->InstallMultipleProtocolInterfaces (
318 &gEfiMtftp4ServiceBindingProtocolGuid
,
319 &MtftpSb
->ServiceBinding
,
323 if (EFI_ERROR (Status
)) {
330 Mtftp4CleanService (MtftpSb
);
337 Callback function which provided by user to remove one node in NetDestroyLinkList process.
339 @param[in] Entry The entry to be removed.
340 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
342 @retval EFI_SUCCESS The entry has been removed successfully.
343 @retval Others Fail to remove the entry.
348 Mtftp4DestroyChildEntryInHandleBuffer (
349 IN LIST_ENTRY
*Entry
,
353 MTFTP4_PROTOCOL
*Instance
;
354 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
355 UINTN NumberOfChildren
;
356 EFI_HANDLE
*ChildHandleBuffer
;
358 if (Entry
== NULL
|| Context
== NULL
) {
359 return EFI_INVALID_PARAMETER
;
362 Instance
= NET_LIST_USER_STRUCT_S (Entry
, MTFTP4_PROTOCOL
, Link
, MTFTP4_PROTOCOL_SIGNATURE
);
363 ServiceBinding
= ((MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->ServiceBinding
;
364 NumberOfChildren
= ((MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->NumberOfChildren
;
365 ChildHandleBuffer
= ((MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->ChildHandleBuffer
;
367 if (!NetIsInHandleBuffer (Instance
->Handle
, NumberOfChildren
, ChildHandleBuffer
)) {
371 return ServiceBinding
->DestroyChild (ServiceBinding
, Instance
->Handle
);
375 Stop the MTFTP driver on controller. The controller is a UDP
378 @param This The MTFTP driver binding protocol
379 @param Controller The controller to stop
380 @param NumberOfChildren The number of children
381 @param ChildHandleBuffer The array of the child handle.
383 @retval EFI_SUCCESS The driver is stopped on the controller.
384 @retval EFI_DEVICE_ERROR Failed to stop the driver on the controller.
389 Mtftp4DriverBindingStop (
390 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
391 IN EFI_HANDLE Controller
,
392 IN UINTN NumberOfChildren
,
393 IN EFI_HANDLE
*ChildHandleBuffer
396 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
397 MTFTP4_SERVICE
*MtftpSb
;
398 EFI_HANDLE NicHandle
;
401 MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context
;
404 // MTFTP driver opens UDP child, So, Controller is a UDP
405 // child handle. Locate the Nic handle first. Then get the
406 // MTFTP private data back.
408 NicHandle
= NetLibGetNicHandle (Controller
, &gEfiUdp4ProtocolGuid
);
410 if (NicHandle
== NULL
) {
414 Status
= gBS
->OpenProtocol (
416 &gEfiMtftp4ServiceBindingProtocolGuid
,
417 (VOID
**) &ServiceBinding
,
418 This
->DriverBindingHandle
,
420 EFI_OPEN_PROTOCOL_GET_PROTOCOL
423 if (EFI_ERROR (Status
)) {
424 return EFI_DEVICE_ERROR
;
427 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (ServiceBinding
);
429 if (!IsListEmpty (&MtftpSb
->Children
)) {
431 // Destroy the Mtftp4 child instance in ChildHandleBuffer.
433 List
= &MtftpSb
->Children
;
434 Context
.ServiceBinding
= ServiceBinding
;
435 Context
.NumberOfChildren
= NumberOfChildren
;
436 Context
.ChildHandleBuffer
= ChildHandleBuffer
;
437 Status
= NetDestroyLinkList (
439 Mtftp4DestroyChildEntryInHandleBuffer
,
445 if (NumberOfChildren
== 0 && IsListEmpty (&MtftpSb
->Children
)) {
446 gBS
->UninstallProtocolInterface (
448 &gEfiMtftp4ServiceBindingProtocolGuid
,
452 Mtftp4CleanService (MtftpSb
);
453 if (gMtftp4ControllerNameTable
!= NULL
) {
454 FreeUnicodeStringTable (gMtftp4ControllerNameTable
);
455 gMtftp4ControllerNameTable
= NULL
;
459 Status
= EFI_SUCCESS
;
467 Initialize a MTFTP protocol instance which is the child of MtftpSb.
469 @param MtftpSb The MTFTP service binding protocol.
470 @param Instance The MTFTP instance to initialize.
475 IN MTFTP4_SERVICE
*MtftpSb
,
476 OUT MTFTP4_PROTOCOL
*Instance
479 ZeroMem (Instance
, sizeof (MTFTP4_PROTOCOL
));
481 Instance
->Signature
= MTFTP4_PROTOCOL_SIGNATURE
;
482 InitializeListHead (&Instance
->Link
);
483 CopyMem (&Instance
->Mtftp4
, &gMtftp4ProtocolTemplate
, sizeof (Instance
->Mtftp4
));
484 Instance
->State
= MTFTP4_STATE_UNCONFIGED
;
485 Instance
->Service
= MtftpSb
;
487 InitializeListHead (&Instance
->Blocks
);
492 Create a MTFTP child for the service binding instance, then
493 install the MTFTP protocol to the ChildHandle.
495 @param This The MTFTP service binding instance.
496 @param ChildHandle The Child handle to install the MTFTP protocol.
498 @retval EFI_INVALID_PARAMETER The parameter is invalid.
499 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the new child.
500 @retval EFI_SUCCESS The child is successfully create.
505 Mtftp4ServiceBindingCreateChild (
506 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
507 IN EFI_HANDLE
*ChildHandle
510 MTFTP4_SERVICE
*MtftpSb
;
511 MTFTP4_PROTOCOL
*Instance
;
516 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
517 return EFI_INVALID_PARAMETER
;
520 Instance
= AllocatePool (sizeof (*Instance
));
522 if (Instance
== NULL
) {
523 return EFI_OUT_OF_RESOURCES
;
526 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (This
);
528 Mtftp4InitProtocol (MtftpSb
, Instance
);
530 Instance
->UnicastPort
= UdpIoCreateIo (
538 if (Instance
->UnicastPort
== NULL
) {
540 return EFI_OUT_OF_RESOURCES
;
544 // Install the MTFTP protocol onto ChildHandle
546 Status
= gBS
->InstallMultipleProtocolInterfaces (
548 &gEfiMtftp4ProtocolGuid
,
553 if (EFI_ERROR (Status
)) {
554 UdpIoFreeIo (Instance
->UnicastPort
);
559 Instance
->Handle
= *ChildHandle
;
562 // Open the Udp4 protocol BY_CHILD.
564 Status
= gBS
->OpenProtocol (
565 MtftpSb
->ConnectUdp
->UdpHandle
,
566 &gEfiUdp4ProtocolGuid
,
568 gMtftp4DriverBinding
.DriverBindingHandle
,
570 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
572 if (EFI_ERROR (Status
)) {
577 // Open the Udp4 protocol by child.
579 Status
= gBS
->OpenProtocol (
580 Instance
->UnicastPort
->UdpHandle
,
581 &gEfiUdp4ProtocolGuid
,
583 gMtftp4DriverBinding
.DriverBindingHandle
,
585 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
587 if (EFI_ERROR (Status
)) {
589 // Close the Udp4 protocol.
592 MtftpSb
->ConnectUdp
->UdpHandle
,
593 &gEfiUdp4ProtocolGuid
,
594 gMtftp4DriverBinding
.DriverBindingHandle
,
601 // Add it to the parent's child list.
603 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
605 InsertTailList (&MtftpSb
->Children
, &Instance
->Link
);
606 MtftpSb
->ChildrenNum
++;
608 gBS
->RestoreTPL (OldTpl
);
613 if (Instance
->Handle
!= NULL
) {
614 gBS
->UninstallMultipleProtocolInterfaces (
616 &gEfiMtftp4ProtocolGuid
,
622 UdpIoFreeIo (Instance
->UnicastPort
);
630 Destroy one of the service binding's child.
632 @param This The service binding instance
633 @param ChildHandle The child handle to destroy
635 @retval EFI_INVALID_PARAMETER The parameter is invaid.
636 @retval EFI_UNSUPPORTED The child may have already been destroyed.
637 @retval EFI_SUCCESS The child is destroyed and removed from the
643 Mtftp4ServiceBindingDestroyChild (
644 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
645 IN EFI_HANDLE ChildHandle
648 MTFTP4_SERVICE
*MtftpSb
;
649 MTFTP4_PROTOCOL
*Instance
;
650 EFI_MTFTP4_PROTOCOL
*Mtftp4
;
654 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
655 return EFI_INVALID_PARAMETER
;
659 // Retrieve the private context data structures
661 Status
= gBS
->OpenProtocol (
663 &gEfiMtftp4ProtocolGuid
,
665 gMtftp4DriverBinding
.DriverBindingHandle
,
667 EFI_OPEN_PROTOCOL_GET_PROTOCOL
670 if (EFI_ERROR (Status
)) {
671 return EFI_UNSUPPORTED
;
674 Instance
= MTFTP4_PROTOCOL_FROM_THIS (Mtftp4
);
675 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (This
);
677 if (Instance
->Service
!= MtftpSb
) {
678 return EFI_INVALID_PARAMETER
;
681 if (Instance
->InDestroy
) {
685 Instance
->InDestroy
= TRUE
;
688 // Close the Udp4 protocol.
691 MtftpSb
->ConnectUdp
->UdpHandle
,
692 &gEfiUdp4ProtocolGuid
,
693 gMtftp4DriverBinding
.DriverBindingHandle
,
698 Instance
->UnicastPort
->UdpHandle
,
699 &gEfiUdp4ProtocolGuid
,
700 gMtftp4DriverBinding
.DriverBindingHandle
,
704 if (Instance
->McastUdpPort
!= NULL
) {
706 Instance
->McastUdpPort
->UdpHandle
,
707 &gEfiUdp4ProtocolGuid
,
708 gMtftp4DriverBinding
.DriverBindingHandle
,
714 // Uninstall the MTFTP4 protocol first to enable a top down destruction.
716 Status
= gBS
->UninstallProtocolInterface (
718 &gEfiMtftp4ProtocolGuid
,
722 if (EFI_ERROR (Status
)) {
723 Instance
->InDestroy
= FALSE
;
727 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
729 Mtftp4CleanOperation (Instance
, EFI_DEVICE_ERROR
);
730 UdpIoFreeIo (Instance
->UnicastPort
);
732 RemoveEntryList (&Instance
->Link
);
733 MtftpSb
->ChildrenNum
--;
735 gBS
->RestoreTPL (OldTpl
);