2 Implementation of Mtftp drivers.
4 Copyright (c) 2006 - 2007, 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 Others MTFTP can't support the controller.
74 Mtftp4DriverBindingSupported (
75 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
76 IN EFI_HANDLE Controller
,
77 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
82 Status
= gBS
->OpenProtocol (
84 &gEfiUdp4ServiceBindingProtocolGuid
,
86 This
->DriverBindingHandle
,
88 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 port to configure
102 @param Context The opaque parameter to the callback
104 @retval EFI_SUCCESS It always return EFI_SUCCESS directly.
108 Mtftp4ConfigNullUdp (
109 IN UDP_IO_PORT
*UdpIo
,
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
->InDestory
= FALSE
;
153 MtftpSb
->ChildrenNum
= 0;
154 InitializeListHead (&MtftpSb
->Children
);
156 MtftpSb
->Timer
= 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
,
173 if (EFI_ERROR (Status
)) {
174 gBS
->FreePool (MtftpSb
);
179 // Create the timer used to time out the procedure which is used to
180 // get the default IP address.
182 Status
= gBS
->CreateEvent (
187 &MtftpSb
->TimerToGetMap
189 if (EFI_ERROR (Status
)) {
190 gBS
->CloseEvent (MtftpSb
->Timer
);
191 gBS
->FreePool (MtftpSb
);
195 MtftpSb
->ConnectUdp
= UdpIoCreatePort (Controller
, Image
, Mtftp4ConfigNullUdp
, NULL
);
197 if (MtftpSb
->ConnectUdp
== NULL
) {
198 gBS
->CloseEvent (MtftpSb
->TimerToGetMap
);
199 gBS
->CloseEvent (MtftpSb
->Timer
);
200 gBS
->FreePool (MtftpSb
);
201 return EFI_DEVICE_ERROR
;
210 Release all the resource used the MTFTP service binding instance.
212 @param MtftpSb The MTFTP service binding instance.
217 IN MTFTP4_SERVICE
*MtftpSb
220 UdpIoFreePort (MtftpSb
->ConnectUdp
);
221 gBS
->CloseEvent (MtftpSb
->TimerToGetMap
);
222 gBS
->CloseEvent (MtftpSb
->Timer
);
227 Start the MTFTP driver on this controller.
229 MTFTP driver will install a MTFTP SERVICE BINDING protocol on the supported
230 controller, which can be used to create/destroy MTFTP children.
232 @param This The MTFTP driver binding protocol.
233 @param Controller The controller to manage.
234 @param RemainingDevicePath Remaining device path.
236 @retval EFI_ALREADY_STARTED The MTFTP service binding protocol has been
237 started on the controller.
238 @retval EFI_SUCCESS The MTFTP service binding is installed on the
244 Mtftp4DriverBindingStart (
245 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
246 IN EFI_HANDLE Controller
,
247 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
250 MTFTP4_SERVICE
*MtftpSb
;
254 // Directly return if driver is already running.
256 Status
= gBS
->OpenProtocol (
258 &gEfiMtftp4ServiceBindingProtocolGuid
,
260 This
->DriverBindingHandle
,
262 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
265 if (Status
== EFI_SUCCESS
) {
266 return EFI_ALREADY_STARTED
;
269 Status
= Mtftp4CreateService (Controller
, This
->DriverBindingHandle
, &MtftpSb
);
271 if (EFI_ERROR (Status
)) {
275 Status
= gBS
->SetTimer (MtftpSb
->Timer
, TimerPeriodic
, TICKS_PER_SECOND
);
277 if (EFI_ERROR (Status
)) {
282 // Install the Mtftp4ServiceBinding Protocol onto Controller
284 Status
= gBS
->InstallMultipleProtocolInterfaces (
286 &gEfiMtftp4ServiceBindingProtocolGuid
,
287 &MtftpSb
->ServiceBinding
,
291 if (EFI_ERROR (Status
)) {
298 Mtftp4CleanService (MtftpSb
);
299 gBS
->FreePool (MtftpSb
);
306 Stop the MTFTP driver on controller. The controller is a UDP
309 @param This The MTFTP driver binding protocol
310 @param Controller The controller to stop
311 @param NumberOfChildren The number of children
312 @param ChildHandleBuffer The array of the child handle.
314 @retval EFI_SUCCESS The driver is stopped on the controller.
315 @retval EFI_DEVICE_ERROR Failed to stop the driver on the controller.
320 Mtftp4DriverBindingStop (
321 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
322 IN EFI_HANDLE Controller
,
323 IN UINTN NumberOfChildren
,
324 IN EFI_HANDLE
*ChildHandleBuffer
327 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
328 MTFTP4_SERVICE
*MtftpSb
;
329 MTFTP4_PROTOCOL
*Instance
;
330 EFI_HANDLE NicHandle
;
335 // MTFTP driver opens UDP child, So, Controller is a UDP
336 // child handle. Locate the Nic handle first. Then get the
337 // MTFTP private data back.
339 NicHandle
= NetLibGetNicHandle (Controller
, &gEfiUdp4ProtocolGuid
);
341 if (NicHandle
== NULL
) {
342 return EFI_DEVICE_ERROR
;
345 Status
= gBS
->OpenProtocol (
347 &gEfiMtftp4ServiceBindingProtocolGuid
,
348 (VOID
**) &ServiceBinding
,
349 This
->DriverBindingHandle
,
351 EFI_OPEN_PROTOCOL_GET_PROTOCOL
354 if (EFI_ERROR (Status
)) {
355 return EFI_DEVICE_ERROR
;
358 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (ServiceBinding
);
360 if (MtftpSb
->InDestory
) {
364 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
366 if (NumberOfChildren
== 0) {
368 MtftpSb
->InDestory
= TRUE
;
370 gBS
->UninstallProtocolInterface (
372 &gEfiMtftp4ServiceBindingProtocolGuid
,
376 Mtftp4CleanService (MtftpSb
);
378 gBS
->FreePool (MtftpSb
);
381 while (!IsListEmpty (&MtftpSb
->Children
)) {
382 Instance
= NET_LIST_HEAD (&MtftpSb
->Children
, MTFTP4_PROTOCOL
, Link
);
383 Mtftp4ServiceBindingDestroyChild (ServiceBinding
, Instance
->Handle
);
386 if (MtftpSb
->ChildrenNum
!= 0) {
387 Status
= EFI_DEVICE_ERROR
;
391 gBS
->RestoreTPL (OldTpl
);
397 Initialize a MTFTP protocol instance which is the child of MtftpSb.
399 @param MtftpSb The MTFTP service binding protocol.
400 @param Instance The MTFTP instance to initialize.
405 IN MTFTP4_SERVICE
*MtftpSb
,
406 OUT MTFTP4_PROTOCOL
*Instance
409 ZeroMem (Instance
, sizeof (MTFTP4_PROTOCOL
));
411 Instance
->Signature
= MTFTP4_PROTOCOL_SIGNATURE
;
412 InitializeListHead (&Instance
->Link
);
413 CopyMem (&Instance
->Mtftp4
, &gMtftp4ProtocolTemplate
, sizeof (Instance
->Mtftp4
));
414 Instance
->State
= MTFTP4_STATE_UNCONFIGED
;
415 Instance
->InDestory
= FALSE
;
416 Instance
->Service
= MtftpSb
;
418 InitializeListHead (&Instance
->Blocks
);
423 Create a MTFTP child for the service binding instance, then
424 install the MTFTP protocol to the ChildHandle.
426 @param This The MTFTP service binding instance.
427 @param ChildHandle The Child handle to install the MTFTP protocol.
429 @retval EFI_INVALID_PARAMETER The parameter is invalid.
430 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the new child.
431 @retval EFI_SUCCESS The child is successfully create.
436 Mtftp4ServiceBindingCreateChild (
437 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
438 IN EFI_HANDLE
*ChildHandle
441 MTFTP4_SERVICE
*MtftpSb
;
442 MTFTP4_PROTOCOL
*Instance
;
447 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
448 return EFI_INVALID_PARAMETER
;
451 Instance
= AllocatePool (sizeof (*Instance
));
453 if (Instance
== NULL
) {
454 return EFI_OUT_OF_RESOURCES
;
457 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (This
);
459 Mtftp4InitProtocol (MtftpSb
, Instance
);
461 Instance
->UnicastPort
= UdpIoCreatePort (
468 if (Instance
->UnicastPort
== NULL
) {
469 gBS
->FreePool (Instance
);
470 return EFI_OUT_OF_RESOURCES
;
474 // Install the MTFTP protocol onto ChildHandle
476 Status
= gBS
->InstallMultipleProtocolInterfaces (
478 &gEfiMtftp4ProtocolGuid
,
483 if (EFI_ERROR (Status
)) {
487 Instance
->Handle
= *ChildHandle
;
490 // Open the Udp4 protocol BY_CHILD.
492 Status
= gBS
->OpenProtocol (
493 MtftpSb
->ConnectUdp
->UdpHandle
,
494 &gEfiUdp4ProtocolGuid
,
496 gMtftp4DriverBinding
.DriverBindingHandle
,
498 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
500 if (EFI_ERROR (Status
)) {
501 gBS
->UninstallMultipleProtocolInterfaces (
503 &gEfiMtftp4ProtocolGuid
,
512 // Add it to the parent's child list.
514 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
516 InsertTailList (&MtftpSb
->Children
, &Instance
->Link
);
517 MtftpSb
->ChildrenNum
++;
519 gBS
->RestoreTPL (OldTpl
);
523 if (EFI_ERROR (Status
)) {
524 UdpIoFreePort (Instance
->UnicastPort
);
525 gBS
->FreePool (Instance
);
533 Destory one of the service binding's child.
535 @param This The service binding instance
536 @param ChildHandle The child handle to destory
538 @retval EFI_INVALID_PARAMETER The parameter is invaid.
539 @retval EFI_UNSUPPORTED The child may have already been destoried.
540 @retval EFI_SUCCESS The child is destoried and removed from the
546 Mtftp4ServiceBindingDestroyChild (
547 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
548 IN EFI_HANDLE ChildHandle
551 MTFTP4_SERVICE
*MtftpSb
;
552 MTFTP4_PROTOCOL
*Instance
;
553 EFI_MTFTP4_PROTOCOL
*Mtftp4
;
557 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
558 return EFI_INVALID_PARAMETER
;
562 // Retrieve the private context data structures
564 Status
= gBS
->OpenProtocol (
566 &gEfiMtftp4ProtocolGuid
,
568 gMtftp4DriverBinding
.DriverBindingHandle
,
570 EFI_OPEN_PROTOCOL_GET_PROTOCOL
573 if (EFI_ERROR (Status
)) {
574 return EFI_UNSUPPORTED
;
577 Instance
= MTFTP4_PROTOCOL_FROM_THIS (Mtftp4
);
578 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (This
);
580 if (Instance
->Service
!= MtftpSb
) {
581 return EFI_INVALID_PARAMETER
;
584 if (Instance
->InDestory
) {
588 Instance
->InDestory
= TRUE
;
591 // Close the Udp4 protocol.
594 MtftpSb
->ConnectUdp
->UdpHandle
,
595 &gEfiUdp4ProtocolGuid
,
596 gMtftp4DriverBinding
.DriverBindingHandle
,
601 // Uninstall the MTFTP4 protocol first to enable a top down destruction.
603 Status
= gBS
->UninstallProtocolInterface (
605 &gEfiMtftp4ProtocolGuid
,
609 if (EFI_ERROR (Status
)) {
610 Instance
->InDestory
= FALSE
;
614 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
616 Mtftp4CleanOperation (Instance
, EFI_DEVICE_ERROR
);
617 UdpIoFreePort (Instance
->UnicastPort
);
619 RemoveEntryList (&Instance
->Link
);
620 MtftpSb
->ChildrenNum
--;
622 gBS
->RestoreTPL (OldTpl
);
624 gBS
->FreePool (Instance
);