2 Implementation of Mtftp drivers.
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php<BR>
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "Mtftp4Impl.h"
17 EFI_DRIVER_BINDING_PROTOCOL gMtftp4DriverBinding
= {
18 Mtftp4DriverBindingSupported
,
19 Mtftp4DriverBindingStart
,
20 Mtftp4DriverBindingStop
,
26 EFI_SERVICE_BINDING_PROTOCOL gMtftp4ServiceBindingTemplete
= {
27 Mtftp4ServiceBindingCreateChild
,
28 Mtftp4ServiceBindingDestroyChild
33 The driver entry point which installs multiple protocols to the ImageHandle.
35 @param ImageHandle The MTFTP's image handle.
36 @param SystemTable The system table.
38 @retval EFI_SUCCESS The handles are successfully installed on the image.
39 @retval others some EFI_ERROR occured.
44 Mtftp4DriverEntryPoint (
45 IN EFI_HANDLE ImageHandle
,
46 IN EFI_SYSTEM_TABLE
*SystemTable
49 return EfiLibInstallDriverBindingComponentName2 (
52 &gMtftp4DriverBinding
,
54 &gMtftp4ComponentName
,
55 &gMtftp4ComponentName2
61 Test whether MTFTP driver support this controller.
63 @param This The MTFTP driver binding instance
64 @param Controller The controller to test
65 @param RemainingDevicePath The remaining device path
67 @retval EFI_SUCCESS The controller has UDP service binding protocol
68 installed, MTFTP can support it.
69 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
70 RemainingDevicePath is already being managed by
71 the driver specified by This.
72 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
73 RemainingDevicePath is already being managed by a
74 different driver or an application that requires
76 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
77 RemainingDevicePath is not supported by the driver
83 Mtftp4DriverBindingSupported (
84 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
85 IN EFI_HANDLE Controller
,
86 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
91 Status
= gBS
->OpenProtocol (
93 &gEfiUdp4ServiceBindingProtocolGuid
,
95 This
->DriverBindingHandle
,
97 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
105 Config a NULL UDP that is used to keep the connection between UDP and MTFTP.
107 Just leave the Udp child unconfigured. When UDP is unloaded,
108 MTFTP will be informed with DriverBinding Stop.
110 @param UdpIo The UDP_IO to configure
111 @param Context The opaque parameter to the callback
113 @retval EFI_SUCCESS It always return EFI_SUCCESS directly.
118 Mtftp4ConfigNullUdp (
128 Create then initialize a MTFTP service binding instance.
130 @param Controller The controller to install the MTFTP service
132 @param Image The driver binding image of the MTFTP driver
133 @param Service The variable to receive the created service
136 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance
137 @retval EFI_DEVICE_ERROR Failed to create a NULL UDP port to keep
139 @retval EFI_SUCCESS The service instance is created for the
144 Mtftp4CreateService (
145 IN EFI_HANDLE Controller
,
147 OUT MTFTP4_SERVICE
**Service
150 MTFTP4_SERVICE
*MtftpSb
;
154 MtftpSb
= AllocatePool (sizeof (MTFTP4_SERVICE
));
156 if (MtftpSb
== NULL
) {
157 return EFI_OUT_OF_RESOURCES
;
160 MtftpSb
->Signature
= MTFTP4_SERVICE_SIGNATURE
;
161 MtftpSb
->ServiceBinding
= gMtftp4ServiceBindingTemplete
;
162 MtftpSb
->ChildrenNum
= 0;
163 InitializeListHead (&MtftpSb
->Children
);
165 MtftpSb
->Timer
= NULL
;
166 MtftpSb
->TimerNotifyLevel
= NULL
;
167 MtftpSb
->TimerToGetMap
= NULL
;
168 MtftpSb
->Controller
= Controller
;
169 MtftpSb
->Image
= Image
;
170 MtftpSb
->ConnectUdp
= NULL
;
173 // Create the timer and a udp to be notified when UDP is uninstalled
175 Status
= gBS
->CreateEvent (
176 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
182 if (EFI_ERROR (Status
)) {
187 Status
= gBS
->CreateEvent (
188 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
190 Mtftp4OnTimerTickNotifyLevel
,
192 &MtftpSb
->TimerNotifyLevel
194 if (EFI_ERROR (Status
)) {
195 gBS
->CloseEvent (MtftpSb
->Timer
);
201 // Create the timer used to time out the procedure which is used to
202 // get the default IP address.
204 Status
= gBS
->CreateEvent (
209 &MtftpSb
->TimerToGetMap
211 if (EFI_ERROR (Status
)) {
212 gBS
->CloseEvent (MtftpSb
->TimerNotifyLevel
);
213 gBS
->CloseEvent (MtftpSb
->Timer
);
218 MtftpSb
->ConnectUdp
= UdpIoCreateIo (
226 if (MtftpSb
->ConnectUdp
== NULL
) {
227 gBS
->CloseEvent (MtftpSb
->TimerToGetMap
);
228 gBS
->CloseEvent (MtftpSb
->TimerNotifyLevel
);
229 gBS
->CloseEvent (MtftpSb
->Timer
);
231 return EFI_DEVICE_ERROR
;
240 Release all the resource used the MTFTP service binding instance.
242 @param MtftpSb The MTFTP service binding instance.
247 IN MTFTP4_SERVICE
*MtftpSb
250 UdpIoFreeIo (MtftpSb
->ConnectUdp
);
251 gBS
->CloseEvent (MtftpSb
->TimerToGetMap
);
252 gBS
->CloseEvent (MtftpSb
->TimerNotifyLevel
);
253 gBS
->CloseEvent (MtftpSb
->Timer
);
258 Start the MTFTP driver on this controller.
260 MTFTP driver will install a MTFTP SERVICE BINDING protocol on the supported
261 controller, which can be used to create/destroy MTFTP children.
263 @param This The MTFTP driver binding protocol.
264 @param Controller The controller to manage.
265 @param RemainingDevicePath Remaining device path.
267 @retval EFI_ALREADY_STARTED The MTFTP service binding protocol has been
268 started on the controller.
269 @retval EFI_SUCCESS The MTFTP service binding is installed on the
275 Mtftp4DriverBindingStart (
276 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
277 IN EFI_HANDLE Controller
,
278 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
281 MTFTP4_SERVICE
*MtftpSb
;
285 // Directly return if driver is already running.
287 Status
= gBS
->OpenProtocol (
289 &gEfiMtftp4ServiceBindingProtocolGuid
,
291 This
->DriverBindingHandle
,
293 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
296 if (Status
== EFI_SUCCESS
) {
297 return EFI_ALREADY_STARTED
;
300 Status
= Mtftp4CreateService (Controller
, This
->DriverBindingHandle
, &MtftpSb
);
302 if (EFI_ERROR (Status
)) {
305 ASSERT (MtftpSb
!= NULL
);
307 Status
= gBS
->SetTimer (MtftpSb
->Timer
, TimerPeriodic
, TICKS_PER_SECOND
);
309 if (EFI_ERROR (Status
)) {
313 Status
= gBS
->SetTimer (MtftpSb
->TimerNotifyLevel
, TimerPeriodic
, TICKS_PER_SECOND
);
315 if (EFI_ERROR (Status
)) {
320 // Install the Mtftp4ServiceBinding Protocol onto Controller
322 Status
= gBS
->InstallMultipleProtocolInterfaces (
324 &gEfiMtftp4ServiceBindingProtocolGuid
,
325 &MtftpSb
->ServiceBinding
,
329 if (EFI_ERROR (Status
)) {
336 Mtftp4CleanService (MtftpSb
);
343 Callback function which provided by user to remove one node in NetDestroyLinkList process.
345 @param[in] Entry The entry to be removed.
346 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
348 @retval EFI_SUCCESS The entry has been removed successfully.
349 @retval Others Fail to remove the entry.
354 Mtftp4DestroyChildEntryInHandleBuffer (
355 IN LIST_ENTRY
*Entry
,
359 MTFTP4_PROTOCOL
*Instance
;
360 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
361 UINTN NumberOfChildren
;
362 EFI_HANDLE
*ChildHandleBuffer
;
364 if (Entry
== NULL
|| Context
== NULL
) {
365 return EFI_INVALID_PARAMETER
;
368 Instance
= NET_LIST_USER_STRUCT_S (Entry
, MTFTP4_PROTOCOL
, Link
, MTFTP4_PROTOCOL_SIGNATURE
);
369 ServiceBinding
= ((MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->ServiceBinding
;
370 NumberOfChildren
= ((MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->NumberOfChildren
;
371 ChildHandleBuffer
= ((MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->ChildHandleBuffer
;
373 if (!NetIsInHandleBuffer (Instance
->Handle
, NumberOfChildren
, ChildHandleBuffer
)) {
377 return ServiceBinding
->DestroyChild (ServiceBinding
, Instance
->Handle
);
381 Stop the MTFTP driver on controller. The controller is a UDP
384 @param This The MTFTP driver binding protocol
385 @param Controller The controller to stop
386 @param NumberOfChildren The number of children
387 @param ChildHandleBuffer The array of the child handle.
389 @retval EFI_SUCCESS The driver is stopped on the controller.
390 @retval EFI_DEVICE_ERROR Failed to stop the driver on the controller.
395 Mtftp4DriverBindingStop (
396 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
397 IN EFI_HANDLE Controller
,
398 IN UINTN NumberOfChildren
,
399 IN EFI_HANDLE
*ChildHandleBuffer
402 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
403 MTFTP4_SERVICE
*MtftpSb
;
404 EFI_HANDLE NicHandle
;
407 MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context
;
410 // MTFTP driver opens UDP child, So, Controller is a UDP
411 // child handle. Locate the Nic handle first. Then get the
412 // MTFTP private data back.
414 NicHandle
= NetLibGetNicHandle (Controller
, &gEfiUdp4ProtocolGuid
);
416 if (NicHandle
== NULL
) {
420 Status
= gBS
->OpenProtocol (
422 &gEfiMtftp4ServiceBindingProtocolGuid
,
423 (VOID
**) &ServiceBinding
,
424 This
->DriverBindingHandle
,
426 EFI_OPEN_PROTOCOL_GET_PROTOCOL
429 if (EFI_ERROR (Status
)) {
430 return EFI_DEVICE_ERROR
;
433 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (ServiceBinding
);
435 if (!IsListEmpty (&MtftpSb
->Children
)) {
437 // Destroy the Mtftp4 child instance in ChildHandleBuffer.
439 List
= &MtftpSb
->Children
;
440 Context
.ServiceBinding
= ServiceBinding
;
441 Context
.NumberOfChildren
= NumberOfChildren
;
442 Context
.ChildHandleBuffer
= ChildHandleBuffer
;
443 Status
= NetDestroyLinkList (
445 Mtftp4DestroyChildEntryInHandleBuffer
,
451 if (NumberOfChildren
== 0 && IsListEmpty (&MtftpSb
->Children
)) {
452 gBS
->UninstallProtocolInterface (
454 &gEfiMtftp4ServiceBindingProtocolGuid
,
458 Mtftp4CleanService (MtftpSb
);
459 if (gMtftp4ControllerNameTable
!= NULL
) {
460 FreeUnicodeStringTable (gMtftp4ControllerNameTable
);
461 gMtftp4ControllerNameTable
= NULL
;
465 Status
= EFI_SUCCESS
;
473 Initialize a MTFTP protocol instance which is the child of MtftpSb.
475 @param MtftpSb The MTFTP service binding protocol.
476 @param Instance The MTFTP instance to initialize.
481 IN MTFTP4_SERVICE
*MtftpSb
,
482 OUT MTFTP4_PROTOCOL
*Instance
485 ZeroMem (Instance
, sizeof (MTFTP4_PROTOCOL
));
487 Instance
->Signature
= MTFTP4_PROTOCOL_SIGNATURE
;
488 InitializeListHead (&Instance
->Link
);
489 CopyMem (&Instance
->Mtftp4
, &gMtftp4ProtocolTemplate
, sizeof (Instance
->Mtftp4
));
490 Instance
->State
= MTFTP4_STATE_UNCONFIGED
;
491 Instance
->Service
= MtftpSb
;
493 InitializeListHead (&Instance
->Blocks
);
498 Create a MTFTP child for the service binding instance, then
499 install the MTFTP protocol to the ChildHandle.
501 @param This The MTFTP service binding instance.
502 @param ChildHandle The Child handle to install the MTFTP protocol.
504 @retval EFI_INVALID_PARAMETER The parameter is invalid.
505 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the new child.
506 @retval EFI_SUCCESS The child is successfully create.
511 Mtftp4ServiceBindingCreateChild (
512 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
513 IN EFI_HANDLE
*ChildHandle
516 MTFTP4_SERVICE
*MtftpSb
;
517 MTFTP4_PROTOCOL
*Instance
;
522 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
523 return EFI_INVALID_PARAMETER
;
526 Instance
= AllocatePool (sizeof (*Instance
));
528 if (Instance
== NULL
) {
529 return EFI_OUT_OF_RESOURCES
;
532 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (This
);
534 Mtftp4InitProtocol (MtftpSb
, Instance
);
536 Instance
->UnicastPort
= UdpIoCreateIo (
544 if (Instance
->UnicastPort
== NULL
) {
546 return EFI_OUT_OF_RESOURCES
;
550 // Install the MTFTP protocol onto ChildHandle
552 Status
= gBS
->InstallMultipleProtocolInterfaces (
554 &gEfiMtftp4ProtocolGuid
,
559 if (EFI_ERROR (Status
)) {
560 UdpIoFreeIo (Instance
->UnicastPort
);
565 Instance
->Handle
= *ChildHandle
;
568 // Open the Udp4 protocol BY_CHILD.
570 Status
= gBS
->OpenProtocol (
571 MtftpSb
->ConnectUdp
->UdpHandle
,
572 &gEfiUdp4ProtocolGuid
,
574 gMtftp4DriverBinding
.DriverBindingHandle
,
576 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
578 if (EFI_ERROR (Status
)) {
583 // Open the Udp4 protocol by child.
585 Status
= gBS
->OpenProtocol (
586 Instance
->UnicastPort
->UdpHandle
,
587 &gEfiUdp4ProtocolGuid
,
589 gMtftp4DriverBinding
.DriverBindingHandle
,
591 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
593 if (EFI_ERROR (Status
)) {
595 // Close the Udp4 protocol.
598 MtftpSb
->ConnectUdp
->UdpHandle
,
599 &gEfiUdp4ProtocolGuid
,
600 gMtftp4DriverBinding
.DriverBindingHandle
,
607 // Add it to the parent's child list.
609 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
611 InsertTailList (&MtftpSb
->Children
, &Instance
->Link
);
612 MtftpSb
->ChildrenNum
++;
614 gBS
->RestoreTPL (OldTpl
);
619 if (Instance
->Handle
!= NULL
) {
620 gBS
->UninstallMultipleProtocolInterfaces (
622 &gEfiMtftp4ProtocolGuid
,
628 UdpIoFreeIo (Instance
->UnicastPort
);
636 Destroy one of the service binding's child.
638 @param This The service binding instance
639 @param ChildHandle The child handle to destroy
641 @retval EFI_INVALID_PARAMETER The parameter is invaid.
642 @retval EFI_UNSUPPORTED The child may have already been destroyed.
643 @retval EFI_SUCCESS The child is destroyed and removed from the
649 Mtftp4ServiceBindingDestroyChild (
650 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
651 IN EFI_HANDLE ChildHandle
654 MTFTP4_SERVICE
*MtftpSb
;
655 MTFTP4_PROTOCOL
*Instance
;
656 EFI_MTFTP4_PROTOCOL
*Mtftp4
;
660 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
661 return EFI_INVALID_PARAMETER
;
665 // Retrieve the private context data structures
667 Status
= gBS
->OpenProtocol (
669 &gEfiMtftp4ProtocolGuid
,
671 gMtftp4DriverBinding
.DriverBindingHandle
,
673 EFI_OPEN_PROTOCOL_GET_PROTOCOL
676 if (EFI_ERROR (Status
)) {
677 return EFI_UNSUPPORTED
;
680 Instance
= MTFTP4_PROTOCOL_FROM_THIS (Mtftp4
);
681 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (This
);
683 if (Instance
->Service
!= MtftpSb
) {
684 return EFI_INVALID_PARAMETER
;
687 if (Instance
->InDestroy
) {
691 Instance
->InDestroy
= TRUE
;
694 // Close the Udp4 protocol.
697 MtftpSb
->ConnectUdp
->UdpHandle
,
698 &gEfiUdp4ProtocolGuid
,
699 gMtftp4DriverBinding
.DriverBindingHandle
,
704 Instance
->UnicastPort
->UdpHandle
,
705 &gEfiUdp4ProtocolGuid
,
706 gMtftp4DriverBinding
.DriverBindingHandle
,
710 if (Instance
->McastUdpPort
!= NULL
) {
712 Instance
->McastUdpPort
->UdpHandle
,
713 &gEfiUdp4ProtocolGuid
,
714 gMtftp4DriverBinding
.DriverBindingHandle
,
720 // Uninstall the MTFTP4 protocol first to enable a top down destruction.
722 Status
= gBS
->UninstallProtocolInterface (
724 &gEfiMtftp4ProtocolGuid
,
728 if (EFI_ERROR (Status
)) {
729 Instance
->InDestroy
= FALSE
;
733 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
735 Mtftp4CleanOperation (Instance
, EFI_DEVICE_ERROR
);
736 UdpIoFreeIo (Instance
->UnicastPort
);
738 RemoveEntryList (&Instance
->Link
);
739 MtftpSb
->ChildrenNum
--;
741 gBS
->RestoreTPL (OldTpl
);