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 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 port to configure
111 @param Context The opaque parameter to the callback
113 @retval EFI_SUCCESS It always return EFI_SUCCESS directly.
117 Mtftp4ConfigNullUdp (
118 IN UDP_IO_PORT
*UdpIo
,
127 Create then initialize a MTFTP service binding instance.
129 @param Controller The controller to install the MTFTP service
131 @param Image The driver binding image of the MTFTP driver
132 @param Service The variable to receive the created service
135 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance
136 @retval EFI_DEVICE_ERROR Failed to create a NULL UDP port to keep
138 @retval EFI_SUCCESS The service instance is created for the
143 Mtftp4CreateService (
144 IN EFI_HANDLE Controller
,
146 OUT MTFTP4_SERVICE
**Service
149 MTFTP4_SERVICE
*MtftpSb
;
153 MtftpSb
= AllocatePool (sizeof (MTFTP4_SERVICE
));
155 if (MtftpSb
== NULL
) {
156 return EFI_OUT_OF_RESOURCES
;
159 MtftpSb
->Signature
= MTFTP4_SERVICE_SIGNATURE
;
160 MtftpSb
->ServiceBinding
= gMtftp4ServiceBindingTemplete
;
161 MtftpSb
->InDestory
= FALSE
;
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
)) {
183 gBS
->FreePool (MtftpSb
);
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
);
200 gBS
->FreePool (MtftpSb
);
204 MtftpSb
->ConnectUdp
= UdpIoCreatePort (Controller
, Image
, Mtftp4ConfigNullUdp
, NULL
);
206 if (MtftpSb
->ConnectUdp
== NULL
) {
207 gBS
->CloseEvent (MtftpSb
->TimerToGetMap
);
208 gBS
->CloseEvent (MtftpSb
->Timer
);
209 gBS
->FreePool (MtftpSb
);
210 return EFI_DEVICE_ERROR
;
219 Release all the resource used the MTFTP service binding instance.
221 @param MtftpSb The MTFTP service binding instance.
226 IN MTFTP4_SERVICE
*MtftpSb
229 UdpIoFreePort (MtftpSb
->ConnectUdp
);
230 gBS
->CloseEvent (MtftpSb
->TimerToGetMap
);
231 gBS
->CloseEvent (MtftpSb
->Timer
);
236 Start the MTFTP driver on this controller.
238 MTFTP driver will install a MTFTP SERVICE BINDING protocol on the supported
239 controller, which can be used to create/destroy MTFTP children.
241 @param This The MTFTP driver binding protocol.
242 @param Controller The controller to manage.
243 @param RemainingDevicePath Remaining device path.
245 @retval EFI_ALREADY_STARTED The MTFTP service binding protocol has been
246 started on the controller.
247 @retval EFI_SUCCESS The MTFTP service binding is installed on the
253 Mtftp4DriverBindingStart (
254 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
255 IN EFI_HANDLE Controller
,
256 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
259 MTFTP4_SERVICE
*MtftpSb
;
263 // Directly return if driver is already running.
265 Status
= gBS
->OpenProtocol (
267 &gEfiMtftp4ServiceBindingProtocolGuid
,
269 This
->DriverBindingHandle
,
271 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
274 if (Status
== EFI_SUCCESS
) {
275 return EFI_ALREADY_STARTED
;
278 Status
= Mtftp4CreateService (Controller
, This
->DriverBindingHandle
, &MtftpSb
);
280 if (EFI_ERROR (Status
)) {
284 Status
= gBS
->SetTimer (MtftpSb
->Timer
, TimerPeriodic
, TICKS_PER_SECOND
);
286 if (EFI_ERROR (Status
)) {
291 // Install the Mtftp4ServiceBinding Protocol onto Controller
293 Status
= gBS
->InstallMultipleProtocolInterfaces (
295 &gEfiMtftp4ServiceBindingProtocolGuid
,
296 &MtftpSb
->ServiceBinding
,
300 if (EFI_ERROR (Status
)) {
307 Mtftp4CleanService (MtftpSb
);
308 gBS
->FreePool (MtftpSb
);
315 Stop the MTFTP driver on controller. The controller is a UDP
318 @param This The MTFTP driver binding protocol
319 @param Controller The controller to stop
320 @param NumberOfChildren The number of children
321 @param ChildHandleBuffer The array of the child handle.
323 @retval EFI_SUCCESS The driver is stopped on the controller.
324 @retval EFI_DEVICE_ERROR Failed to stop the driver on the controller.
329 Mtftp4DriverBindingStop (
330 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
331 IN EFI_HANDLE Controller
,
332 IN UINTN NumberOfChildren
,
333 IN EFI_HANDLE
*ChildHandleBuffer
336 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
337 MTFTP4_SERVICE
*MtftpSb
;
338 MTFTP4_PROTOCOL
*Instance
;
339 EFI_HANDLE NicHandle
;
344 // MTFTP driver opens UDP child, So, Controller is a UDP
345 // child handle. Locate the Nic handle first. Then get the
346 // MTFTP private data back.
348 NicHandle
= NetLibGetNicHandle (Controller
, &gEfiUdp4ProtocolGuid
);
350 if (NicHandle
== NULL
) {
351 return EFI_DEVICE_ERROR
;
354 Status
= gBS
->OpenProtocol (
356 &gEfiMtftp4ServiceBindingProtocolGuid
,
357 (VOID
**) &ServiceBinding
,
358 This
->DriverBindingHandle
,
360 EFI_OPEN_PROTOCOL_GET_PROTOCOL
363 if (EFI_ERROR (Status
)) {
364 return EFI_DEVICE_ERROR
;
367 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (ServiceBinding
);
369 if (MtftpSb
->InDestory
) {
373 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
375 if (NumberOfChildren
== 0) {
377 MtftpSb
->InDestory
= TRUE
;
379 gBS
->UninstallProtocolInterface (
381 &gEfiMtftp4ServiceBindingProtocolGuid
,
385 Mtftp4CleanService (MtftpSb
);
387 gBS
->FreePool (MtftpSb
);
390 while (!IsListEmpty (&MtftpSb
->Children
)) {
391 Instance
= NET_LIST_HEAD (&MtftpSb
->Children
, MTFTP4_PROTOCOL
, Link
);
392 Mtftp4ServiceBindingDestroyChild (ServiceBinding
, Instance
->Handle
);
395 if (MtftpSb
->ChildrenNum
!= 0) {
396 Status
= EFI_DEVICE_ERROR
;
400 gBS
->RestoreTPL (OldTpl
);
406 Initialize a MTFTP protocol instance which is the child of MtftpSb.
408 @param MtftpSb The MTFTP service binding protocol.
409 @param Instance The MTFTP instance to initialize.
414 IN MTFTP4_SERVICE
*MtftpSb
,
415 OUT MTFTP4_PROTOCOL
*Instance
418 ZeroMem (Instance
, sizeof (MTFTP4_PROTOCOL
));
420 Instance
->Signature
= MTFTP4_PROTOCOL_SIGNATURE
;
421 InitializeListHead (&Instance
->Link
);
422 CopyMem (&Instance
->Mtftp4
, &gMtftp4ProtocolTemplate
, sizeof (Instance
->Mtftp4
));
423 Instance
->State
= MTFTP4_STATE_UNCONFIGED
;
424 Instance
->InDestory
= FALSE
;
425 Instance
->Service
= MtftpSb
;
427 InitializeListHead (&Instance
->Blocks
);
432 Create a MTFTP child for the service binding instance, then
433 install the MTFTP protocol to the ChildHandle.
435 @param This The MTFTP service binding instance.
436 @param ChildHandle The Child handle to install the MTFTP protocol.
438 @retval EFI_INVALID_PARAMETER The parameter is invalid.
439 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the new child.
440 @retval EFI_SUCCESS The child is successfully create.
445 Mtftp4ServiceBindingCreateChild (
446 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
447 IN EFI_HANDLE
*ChildHandle
450 MTFTP4_SERVICE
*MtftpSb
;
451 MTFTP4_PROTOCOL
*Instance
;
456 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
457 return EFI_INVALID_PARAMETER
;
460 Instance
= AllocatePool (sizeof (*Instance
));
462 if (Instance
== NULL
) {
463 return EFI_OUT_OF_RESOURCES
;
466 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (This
);
468 Mtftp4InitProtocol (MtftpSb
, Instance
);
470 Instance
->UnicastPort
= UdpIoCreatePort (
477 if (Instance
->UnicastPort
== NULL
) {
478 gBS
->FreePool (Instance
);
479 return EFI_OUT_OF_RESOURCES
;
483 // Install the MTFTP protocol onto ChildHandle
485 Status
= gBS
->InstallMultipleProtocolInterfaces (
487 &gEfiMtftp4ProtocolGuid
,
492 if (EFI_ERROR (Status
)) {
496 Instance
->Handle
= *ChildHandle
;
499 // Open the Udp4 protocol BY_CHILD.
501 Status
= gBS
->OpenProtocol (
502 MtftpSb
->ConnectUdp
->UdpHandle
,
503 &gEfiUdp4ProtocolGuid
,
505 gMtftp4DriverBinding
.DriverBindingHandle
,
507 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
509 if (EFI_ERROR (Status
)) {
510 gBS
->UninstallMultipleProtocolInterfaces (
512 &gEfiMtftp4ProtocolGuid
,
521 // Add it to the parent's child list.
523 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
525 InsertTailList (&MtftpSb
->Children
, &Instance
->Link
);
526 MtftpSb
->ChildrenNum
++;
528 gBS
->RestoreTPL (OldTpl
);
532 if (EFI_ERROR (Status
)) {
533 UdpIoFreePort (Instance
->UnicastPort
);
534 gBS
->FreePool (Instance
);
542 Destory one of the service binding's child.
544 @param This The service binding instance
545 @param ChildHandle The child handle to destory
547 @retval EFI_INVALID_PARAMETER The parameter is invaid.
548 @retval EFI_UNSUPPORTED The child may have already been destoried.
549 @retval EFI_SUCCESS The child is destoried and removed from the
555 Mtftp4ServiceBindingDestroyChild (
556 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
557 IN EFI_HANDLE ChildHandle
560 MTFTP4_SERVICE
*MtftpSb
;
561 MTFTP4_PROTOCOL
*Instance
;
562 EFI_MTFTP4_PROTOCOL
*Mtftp4
;
566 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
567 return EFI_INVALID_PARAMETER
;
571 // Retrieve the private context data structures
573 Status
= gBS
->OpenProtocol (
575 &gEfiMtftp4ProtocolGuid
,
577 gMtftp4DriverBinding
.DriverBindingHandle
,
579 EFI_OPEN_PROTOCOL_GET_PROTOCOL
582 if (EFI_ERROR (Status
)) {
583 return EFI_UNSUPPORTED
;
586 Instance
= MTFTP4_PROTOCOL_FROM_THIS (Mtftp4
);
587 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (This
);
589 if (Instance
->Service
!= MtftpSb
) {
590 return EFI_INVALID_PARAMETER
;
593 if (Instance
->InDestory
) {
597 Instance
->InDestory
= TRUE
;
600 // Close the Udp4 protocol.
603 MtftpSb
->ConnectUdp
->UdpHandle
,
604 &gEfiUdp4ProtocolGuid
,
605 gMtftp4DriverBinding
.DriverBindingHandle
,
610 // Uninstall the MTFTP4 protocol first to enable a top down destruction.
612 Status
= gBS
->UninstallProtocolInterface (
614 &gEfiMtftp4ProtocolGuid
,
618 if (EFI_ERROR (Status
)) {
619 Instance
->InDestory
= FALSE
;
623 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
625 Mtftp4CleanOperation (Instance
, EFI_DEVICE_ERROR
);
626 UdpIoFreePort (Instance
->UnicastPort
);
628 RemoveEntryList (&Instance
->Link
);
629 MtftpSb
->ChildrenNum
--;
631 gBS
->RestoreTPL (OldTpl
);
633 gBS
->FreePool (Instance
);