2 Implementation of Mtftp drivers.
4 Copyright (c) 2006 - 2010, Intel Corporation<BR>
5 All rights reserved. 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
->InDestory
= FALSE
;
163 MtftpSb
->ChildrenNum
= 0;
164 InitializeListHead (&MtftpSb
->Children
);
166 MtftpSb
->Timer
= 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
,
183 if (EFI_ERROR (Status
)) {
189 // Create the timer used to time out the procedure which is used to
190 // get the default IP address.
192 Status
= gBS
->CreateEvent (
197 &MtftpSb
->TimerToGetMap
199 if (EFI_ERROR (Status
)) {
200 gBS
->CloseEvent (MtftpSb
->Timer
);
205 MtftpSb
->ConnectUdp
= UdpIoCreateIo (
213 if (MtftpSb
->ConnectUdp
== NULL
) {
214 gBS
->CloseEvent (MtftpSb
->TimerToGetMap
);
215 gBS
->CloseEvent (MtftpSb
->Timer
);
217 return EFI_DEVICE_ERROR
;
226 Release all the resource used the MTFTP service binding instance.
228 @param MtftpSb The MTFTP service binding instance.
233 IN MTFTP4_SERVICE
*MtftpSb
236 UdpIoFreeIo (MtftpSb
->ConnectUdp
);
237 gBS
->CloseEvent (MtftpSb
->TimerToGetMap
);
238 gBS
->CloseEvent (MtftpSb
->Timer
);
243 Start the MTFTP driver on this controller.
245 MTFTP driver will install a MTFTP SERVICE BINDING protocol on the supported
246 controller, which can be used to create/destroy MTFTP children.
248 @param This The MTFTP driver binding protocol.
249 @param Controller The controller to manage.
250 @param RemainingDevicePath Remaining device path.
252 @retval EFI_ALREADY_STARTED The MTFTP service binding protocol has been
253 started on the controller.
254 @retval EFI_SUCCESS The MTFTP service binding is installed on the
260 Mtftp4DriverBindingStart (
261 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
262 IN EFI_HANDLE Controller
,
263 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
266 MTFTP4_SERVICE
*MtftpSb
;
270 // Directly return if driver is already running.
272 Status
= gBS
->OpenProtocol (
274 &gEfiMtftp4ServiceBindingProtocolGuid
,
276 This
->DriverBindingHandle
,
278 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
281 if (Status
== EFI_SUCCESS
) {
282 return EFI_ALREADY_STARTED
;
285 Status
= Mtftp4CreateService (Controller
, This
->DriverBindingHandle
, &MtftpSb
);
287 if (EFI_ERROR (Status
)) {
290 ASSERT (MtftpSb
!= NULL
);
292 Status
= gBS
->SetTimer (MtftpSb
->Timer
, TimerPeriodic
, TICKS_PER_SECOND
);
294 if (EFI_ERROR (Status
)) {
299 // Install the Mtftp4ServiceBinding Protocol onto Controller
301 Status
= gBS
->InstallMultipleProtocolInterfaces (
303 &gEfiMtftp4ServiceBindingProtocolGuid
,
304 &MtftpSb
->ServiceBinding
,
308 if (EFI_ERROR (Status
)) {
315 Mtftp4CleanService (MtftpSb
);
323 Stop the MTFTP driver on controller. The controller is a UDP
326 @param This The MTFTP driver binding protocol
327 @param Controller The controller to stop
328 @param NumberOfChildren The number of children
329 @param ChildHandleBuffer The array of the child handle.
331 @retval EFI_SUCCESS The driver is stopped on the controller.
332 @retval EFI_DEVICE_ERROR Failed to stop the driver on the controller.
337 Mtftp4DriverBindingStop (
338 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
339 IN EFI_HANDLE Controller
,
340 IN UINTN NumberOfChildren
,
341 IN EFI_HANDLE
*ChildHandleBuffer
344 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
345 MTFTP4_SERVICE
*MtftpSb
;
346 MTFTP4_PROTOCOL
*Instance
;
347 EFI_HANDLE NicHandle
;
352 // MTFTP driver opens UDP child, So, Controller is a UDP
353 // child handle. Locate the Nic handle first. Then get the
354 // MTFTP private data back.
356 NicHandle
= NetLibGetNicHandle (Controller
, &gEfiUdp4ProtocolGuid
);
358 if (NicHandle
== NULL
) {
359 return EFI_DEVICE_ERROR
;
362 Status
= gBS
->OpenProtocol (
364 &gEfiMtftp4ServiceBindingProtocolGuid
,
365 (VOID
**) &ServiceBinding
,
366 This
->DriverBindingHandle
,
368 EFI_OPEN_PROTOCOL_GET_PROTOCOL
371 if (EFI_ERROR (Status
)) {
372 return EFI_DEVICE_ERROR
;
375 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (ServiceBinding
);
377 if (MtftpSb
->InDestory
) {
381 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
383 if (NumberOfChildren
== 0) {
385 MtftpSb
->InDestory
= TRUE
;
387 gBS
->UninstallProtocolInterface (
389 &gEfiMtftp4ServiceBindingProtocolGuid
,
393 Mtftp4CleanService (MtftpSb
);
398 while (!IsListEmpty (&MtftpSb
->Children
)) {
399 Instance
= NET_LIST_HEAD (&MtftpSb
->Children
, MTFTP4_PROTOCOL
, Link
);
400 Mtftp4ServiceBindingDestroyChild (ServiceBinding
, Instance
->Handle
);
403 if (MtftpSb
->ChildrenNum
!= 0) {
404 Status
= EFI_DEVICE_ERROR
;
408 gBS
->RestoreTPL (OldTpl
);
414 Initialize a MTFTP protocol instance which is the child of MtftpSb.
416 @param MtftpSb The MTFTP service binding protocol.
417 @param Instance The MTFTP instance to initialize.
422 IN MTFTP4_SERVICE
*MtftpSb
,
423 OUT MTFTP4_PROTOCOL
*Instance
426 ZeroMem (Instance
, sizeof (MTFTP4_PROTOCOL
));
428 Instance
->Signature
= MTFTP4_PROTOCOL_SIGNATURE
;
429 InitializeListHead (&Instance
->Link
);
430 CopyMem (&Instance
->Mtftp4
, &gMtftp4ProtocolTemplate
, sizeof (Instance
->Mtftp4
));
431 Instance
->State
= MTFTP4_STATE_UNCONFIGED
;
432 Instance
->InDestory
= FALSE
;
433 Instance
->Service
= MtftpSb
;
435 InitializeListHead (&Instance
->Blocks
);
440 Create a MTFTP child for the service binding instance, then
441 install the MTFTP protocol to the ChildHandle.
443 @param This The MTFTP service binding instance.
444 @param ChildHandle The Child handle to install the MTFTP protocol.
446 @retval EFI_INVALID_PARAMETER The parameter is invalid.
447 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the new child.
448 @retval EFI_SUCCESS The child is successfully create.
453 Mtftp4ServiceBindingCreateChild (
454 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
455 IN EFI_HANDLE
*ChildHandle
458 MTFTP4_SERVICE
*MtftpSb
;
459 MTFTP4_PROTOCOL
*Instance
;
464 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
465 return EFI_INVALID_PARAMETER
;
468 Instance
= AllocatePool (sizeof (*Instance
));
470 if (Instance
== NULL
) {
471 return EFI_OUT_OF_RESOURCES
;
474 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (This
);
476 Mtftp4InitProtocol (MtftpSb
, Instance
);
478 Instance
->UnicastPort
= UdpIoCreateIo (
486 if (Instance
->UnicastPort
== NULL
) {
488 return EFI_OUT_OF_RESOURCES
;
492 // Install the MTFTP protocol onto ChildHandle
494 Status
= gBS
->InstallMultipleProtocolInterfaces (
496 &gEfiMtftp4ProtocolGuid
,
501 if (EFI_ERROR (Status
)) {
505 Instance
->Handle
= *ChildHandle
;
508 // Open the Udp4 protocol BY_CHILD.
510 Status
= gBS
->OpenProtocol (
511 MtftpSb
->ConnectUdp
->UdpHandle
,
512 &gEfiUdp4ProtocolGuid
,
514 gMtftp4DriverBinding
.DriverBindingHandle
,
516 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
518 if (EFI_ERROR (Status
)) {
519 gBS
->UninstallMultipleProtocolInterfaces (
521 &gEfiMtftp4ProtocolGuid
,
530 // Add it to the parent's child list.
532 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
534 InsertTailList (&MtftpSb
->Children
, &Instance
->Link
);
535 MtftpSb
->ChildrenNum
++;
537 gBS
->RestoreTPL (OldTpl
);
541 if (EFI_ERROR (Status
)) {
542 UdpIoFreeIo (Instance
->UnicastPort
);
551 Destory one of the service binding's child.
553 @param This The service binding instance
554 @param ChildHandle The child handle to destory
556 @retval EFI_INVALID_PARAMETER The parameter is invaid.
557 @retval EFI_UNSUPPORTED The child may have already been destoried.
558 @retval EFI_SUCCESS The child is destoried and removed from the
564 Mtftp4ServiceBindingDestroyChild (
565 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
566 IN EFI_HANDLE ChildHandle
569 MTFTP4_SERVICE
*MtftpSb
;
570 MTFTP4_PROTOCOL
*Instance
;
571 EFI_MTFTP4_PROTOCOL
*Mtftp4
;
575 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
576 return EFI_INVALID_PARAMETER
;
580 // Retrieve the private context data structures
582 Status
= gBS
->OpenProtocol (
584 &gEfiMtftp4ProtocolGuid
,
586 gMtftp4DriverBinding
.DriverBindingHandle
,
588 EFI_OPEN_PROTOCOL_GET_PROTOCOL
591 if (EFI_ERROR (Status
)) {
592 return EFI_UNSUPPORTED
;
595 Instance
= MTFTP4_PROTOCOL_FROM_THIS (Mtftp4
);
596 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (This
);
598 if (Instance
->Service
!= MtftpSb
) {
599 return EFI_INVALID_PARAMETER
;
602 if (Instance
->InDestory
) {
606 Instance
->InDestory
= TRUE
;
609 // Close the Udp4 protocol.
612 MtftpSb
->ConnectUdp
->UdpHandle
,
613 &gEfiUdp4ProtocolGuid
,
614 gMtftp4DriverBinding
.DriverBindingHandle
,
619 // Uninstall the MTFTP4 protocol first to enable a top down destruction.
621 Status
= gBS
->UninstallProtocolInterface (
623 &gEfiMtftp4ProtocolGuid
,
627 if (EFI_ERROR (Status
)) {
628 Instance
->InDestory
= FALSE
;
632 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
634 Mtftp4CleanOperation (Instance
, EFI_DEVICE_ERROR
);
635 UdpIoFreeIo (Instance
->UnicastPort
);
637 RemoveEntryList (&Instance
->Link
);
638 MtftpSb
->ChildrenNum
--;
640 gBS
->RestoreTPL (OldTpl
);