2 Implementation of Mtftp drivers.
4 Copyright (c) 2006 - 2012, 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
->TimerToGetMap
= NULL
;
167 MtftpSb
->Controller
= Controller
;
168 MtftpSb
->Image
= Image
;
169 MtftpSb
->ConnectUdp
= NULL
;
172 // Create the timer and a udp to be notified when UDP is uninstalled
174 Status
= gBS
->CreateEvent (
175 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
182 if (EFI_ERROR (Status
)) {
188 // Create the timer used to time out the procedure which is used to
189 // get the default IP address.
191 Status
= gBS
->CreateEvent (
196 &MtftpSb
->TimerToGetMap
198 if (EFI_ERROR (Status
)) {
199 gBS
->CloseEvent (MtftpSb
->Timer
);
204 MtftpSb
->ConnectUdp
= UdpIoCreateIo (
212 if (MtftpSb
->ConnectUdp
== NULL
) {
213 gBS
->CloseEvent (MtftpSb
->TimerToGetMap
);
214 gBS
->CloseEvent (MtftpSb
->Timer
);
216 return EFI_DEVICE_ERROR
;
225 Release all the resource used the MTFTP service binding instance.
227 @param MtftpSb The MTFTP service binding instance.
232 IN MTFTP4_SERVICE
*MtftpSb
235 UdpIoFreeIo (MtftpSb
->ConnectUdp
);
236 gBS
->CloseEvent (MtftpSb
->TimerToGetMap
);
237 gBS
->CloseEvent (MtftpSb
->Timer
);
242 Start the MTFTP driver on this controller.
244 MTFTP driver will install a MTFTP SERVICE BINDING protocol on the supported
245 controller, which can be used to create/destroy MTFTP children.
247 @param This The MTFTP driver binding protocol.
248 @param Controller The controller to manage.
249 @param RemainingDevicePath Remaining device path.
251 @retval EFI_ALREADY_STARTED The MTFTP service binding protocol has been
252 started on the controller.
253 @retval EFI_SUCCESS The MTFTP service binding is installed on the
259 Mtftp4DriverBindingStart (
260 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
261 IN EFI_HANDLE Controller
,
262 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
265 MTFTP4_SERVICE
*MtftpSb
;
269 // Directly return if driver is already running.
271 Status
= gBS
->OpenProtocol (
273 &gEfiMtftp4ServiceBindingProtocolGuid
,
275 This
->DriverBindingHandle
,
277 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
280 if (Status
== EFI_SUCCESS
) {
281 return EFI_ALREADY_STARTED
;
284 Status
= Mtftp4CreateService (Controller
, This
->DriverBindingHandle
, &MtftpSb
);
286 if (EFI_ERROR (Status
)) {
289 ASSERT (MtftpSb
!= NULL
);
291 Status
= gBS
->SetTimer (MtftpSb
->Timer
, TimerPeriodic
, TICKS_PER_SECOND
);
293 if (EFI_ERROR (Status
)) {
298 // Install the Mtftp4ServiceBinding Protocol onto Controller
300 Status
= gBS
->InstallMultipleProtocolInterfaces (
302 &gEfiMtftp4ServiceBindingProtocolGuid
,
303 &MtftpSb
->ServiceBinding
,
307 if (EFI_ERROR (Status
)) {
314 Mtftp4CleanService (MtftpSb
);
321 Callback function which provided by user to remove one node in NetDestroyLinkList process.
323 @param[in] Entry The entry to be removed.
324 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
326 @retval EFI_SUCCESS The entry has been removed successfully.
327 @retval Others Fail to remove the entry.
331 Mtftp4DestroyChildEntryInHandleBuffer (
332 IN LIST_ENTRY
*Entry
,
336 MTFTP4_PROTOCOL
*Instance
;
337 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
338 UINTN NumberOfChildren
;
339 EFI_HANDLE
*ChildHandleBuffer
;
341 if (Entry
== NULL
|| Context
== NULL
) {
342 return EFI_INVALID_PARAMETER
;
345 Instance
= NET_LIST_USER_STRUCT_S (Entry
, MTFTP4_PROTOCOL
, Link
, MTFTP4_PROTOCOL_SIGNATURE
);
346 ServiceBinding
= ((MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->ServiceBinding
;
347 NumberOfChildren
= ((MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->NumberOfChildren
;
348 ChildHandleBuffer
= ((MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->ChildHandleBuffer
;
350 if (!NetIsInHandleBuffer (Instance
->Handle
, NumberOfChildren
, ChildHandleBuffer
)) {
354 return ServiceBinding
->DestroyChild (ServiceBinding
, Instance
->Handle
);
358 Stop the MTFTP driver on controller. The controller is a UDP
361 @param This The MTFTP driver binding protocol
362 @param Controller The controller to stop
363 @param NumberOfChildren The number of children
364 @param ChildHandleBuffer The array of the child handle.
366 @retval EFI_SUCCESS The driver is stopped on the controller.
367 @retval EFI_DEVICE_ERROR Failed to stop the driver on the controller.
372 Mtftp4DriverBindingStop (
373 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
374 IN EFI_HANDLE Controller
,
375 IN UINTN NumberOfChildren
,
376 IN EFI_HANDLE
*ChildHandleBuffer
379 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
380 MTFTP4_SERVICE
*MtftpSb
;
381 EFI_HANDLE NicHandle
;
384 MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context
;
387 // MTFTP driver opens UDP child, So, Controller is a UDP
388 // child handle. Locate the Nic handle first. Then get the
389 // MTFTP private data back.
391 NicHandle
= NetLibGetNicHandle (Controller
, &gEfiUdp4ProtocolGuid
);
393 if (NicHandle
== NULL
) {
397 Status
= gBS
->OpenProtocol (
399 &gEfiMtftp4ServiceBindingProtocolGuid
,
400 (VOID
**) &ServiceBinding
,
401 This
->DriverBindingHandle
,
403 EFI_OPEN_PROTOCOL_GET_PROTOCOL
406 if (EFI_ERROR (Status
)) {
407 return EFI_DEVICE_ERROR
;
410 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (ServiceBinding
);
412 if (!IsListEmpty (&MtftpSb
->Children
)) {
414 // Destroy the Mtftp4 child instance in ChildHandleBuffer.
416 List
= &MtftpSb
->Children
;
417 Context
.ServiceBinding
= ServiceBinding
;
418 Context
.NumberOfChildren
= NumberOfChildren
;
419 Context
.ChildHandleBuffer
= ChildHandleBuffer
;
420 Status
= NetDestroyLinkList (
422 Mtftp4DestroyChildEntryInHandleBuffer
,
428 if (NumberOfChildren
== 0 && IsListEmpty (&MtftpSb
->Children
)) {
429 gBS
->UninstallProtocolInterface (
431 &gEfiMtftp4ServiceBindingProtocolGuid
,
435 Mtftp4CleanService (MtftpSb
);
436 if (gMtftp4ControllerNameTable
!= NULL
) {
437 FreeUnicodeStringTable (gMtftp4ControllerNameTable
);
438 gMtftp4ControllerNameTable
= NULL
;
442 Status
= EFI_SUCCESS
;
450 Initialize a MTFTP protocol instance which is the child of MtftpSb.
452 @param MtftpSb The MTFTP service binding protocol.
453 @param Instance The MTFTP instance to initialize.
458 IN MTFTP4_SERVICE
*MtftpSb
,
459 OUT MTFTP4_PROTOCOL
*Instance
462 ZeroMem (Instance
, sizeof (MTFTP4_PROTOCOL
));
464 Instance
->Signature
= MTFTP4_PROTOCOL_SIGNATURE
;
465 InitializeListHead (&Instance
->Link
);
466 CopyMem (&Instance
->Mtftp4
, &gMtftp4ProtocolTemplate
, sizeof (Instance
->Mtftp4
));
467 Instance
->State
= MTFTP4_STATE_UNCONFIGED
;
468 Instance
->Service
= MtftpSb
;
470 InitializeListHead (&Instance
->Blocks
);
475 Create a MTFTP child for the service binding instance, then
476 install the MTFTP protocol to the ChildHandle.
478 @param This The MTFTP service binding instance.
479 @param ChildHandle The Child handle to install the MTFTP protocol.
481 @retval EFI_INVALID_PARAMETER The parameter is invalid.
482 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the new child.
483 @retval EFI_SUCCESS The child is successfully create.
488 Mtftp4ServiceBindingCreateChild (
489 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
490 IN EFI_HANDLE
*ChildHandle
493 MTFTP4_SERVICE
*MtftpSb
;
494 MTFTP4_PROTOCOL
*Instance
;
499 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
500 return EFI_INVALID_PARAMETER
;
503 Instance
= AllocatePool (sizeof (*Instance
));
505 if (Instance
== NULL
) {
506 return EFI_OUT_OF_RESOURCES
;
509 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (This
);
511 Mtftp4InitProtocol (MtftpSb
, Instance
);
513 Instance
->UnicastPort
= UdpIoCreateIo (
521 if (Instance
->UnicastPort
== NULL
) {
523 return EFI_OUT_OF_RESOURCES
;
527 // Install the MTFTP protocol onto ChildHandle
529 Status
= gBS
->InstallMultipleProtocolInterfaces (
531 &gEfiMtftp4ProtocolGuid
,
536 if (EFI_ERROR (Status
)) {
537 UdpIoFreeIo (Instance
->UnicastPort
);
542 Instance
->Handle
= *ChildHandle
;
545 // Open the Udp4 protocol BY_CHILD.
547 Status
= gBS
->OpenProtocol (
548 MtftpSb
->ConnectUdp
->UdpHandle
,
549 &gEfiUdp4ProtocolGuid
,
551 gMtftp4DriverBinding
.DriverBindingHandle
,
553 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
555 if (EFI_ERROR (Status
)) {
560 // Open the Udp4 protocol by child.
562 Status
= gBS
->OpenProtocol (
563 Instance
->UnicastPort
->UdpHandle
,
564 &gEfiUdp4ProtocolGuid
,
566 gMtftp4DriverBinding
.DriverBindingHandle
,
568 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
570 if (EFI_ERROR (Status
)) {
572 // Close the Udp4 protocol.
575 MtftpSb
->ConnectUdp
->UdpHandle
,
576 &gEfiUdp4ProtocolGuid
,
577 gMtftp4DriverBinding
.DriverBindingHandle
,
584 // Add it to the parent's child list.
586 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
588 InsertTailList (&MtftpSb
->Children
, &Instance
->Link
);
589 MtftpSb
->ChildrenNum
++;
591 gBS
->RestoreTPL (OldTpl
);
596 if (Instance
->Handle
!= NULL
) {
597 gBS
->UninstallMultipleProtocolInterfaces (
599 &gEfiMtftp4ProtocolGuid
,
605 UdpIoFreeIo (Instance
->UnicastPort
);
613 Destroy one of the service binding's child.
615 @param This The service binding instance
616 @param ChildHandle The child handle to destroy
618 @retval EFI_INVALID_PARAMETER The parameter is invaid.
619 @retval EFI_UNSUPPORTED The child may have already been destroyed.
620 @retval EFI_SUCCESS The child is destroyed and removed from the
626 Mtftp4ServiceBindingDestroyChild (
627 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
628 IN EFI_HANDLE ChildHandle
631 MTFTP4_SERVICE
*MtftpSb
;
632 MTFTP4_PROTOCOL
*Instance
;
633 EFI_MTFTP4_PROTOCOL
*Mtftp4
;
637 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
638 return EFI_INVALID_PARAMETER
;
642 // Retrieve the private context data structures
644 Status
= gBS
->OpenProtocol (
646 &gEfiMtftp4ProtocolGuid
,
648 gMtftp4DriverBinding
.DriverBindingHandle
,
650 EFI_OPEN_PROTOCOL_GET_PROTOCOL
653 if (EFI_ERROR (Status
)) {
654 return EFI_UNSUPPORTED
;
657 Instance
= MTFTP4_PROTOCOL_FROM_THIS (Mtftp4
);
658 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (This
);
660 if (Instance
->Service
!= MtftpSb
) {
661 return EFI_INVALID_PARAMETER
;
664 if (Instance
->InDestroy
) {
668 Instance
->InDestroy
= TRUE
;
671 // Close the Udp4 protocol.
674 MtftpSb
->ConnectUdp
->UdpHandle
,
675 &gEfiUdp4ProtocolGuid
,
676 gMtftp4DriverBinding
.DriverBindingHandle
,
681 Instance
->UnicastPort
->UdpHandle
,
682 &gEfiUdp4ProtocolGuid
,
683 gMtftp4DriverBinding
.DriverBindingHandle
,
687 if (Instance
->McastUdpPort
!= NULL
) {
689 Instance
->McastUdpPort
->UdpHandle
,
690 &gEfiUdp4ProtocolGuid
,
691 gMtftp4DriverBinding
.DriverBindingHandle
,
697 // Uninstall the MTFTP4 protocol first to enable a top down destruction.
699 Status
= gBS
->UninstallProtocolInterface (
701 &gEfiMtftp4ProtocolGuid
,
705 if (EFI_ERROR (Status
)) {
706 Instance
->InDestroy
= FALSE
;
710 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
712 Mtftp4CleanOperation (Instance
, EFI_DEVICE_ERROR
);
713 UdpIoFreeIo (Instance
->UnicastPort
);
715 RemoveEntryList (&Instance
->Link
);
716 MtftpSb
->ChildrenNum
--;
718 gBS
->RestoreTPL (OldTpl
);