3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 #include "Mtftp4Impl.h"
23 EFI_DRIVER_BINDING_PROTOCOL gMtftp4DriverBinding
= {
24 Mtftp4DriverBindingSupported
,
25 Mtftp4DriverBindingStart
,
26 Mtftp4DriverBindingStop
,
32 EFI_SERVICE_BINDING_PROTOCOL gMtftp4ServiceBindingTemplete
= {
33 Mtftp4ServiceBindingCreateChild
,
34 Mtftp4ServiceBindingDestroyChild
39 Mtftp4DriverEntryPoint (
40 IN EFI_HANDLE ImageHandle
,
41 IN EFI_SYSTEM_TABLE
*SystemTable
47 The driver entry point which installs multiple protocols to the ImageHandle.
51 ImageHandle - The MTFTP's image handle
52 SystemTable - The system table
56 EFI_SUCCESS - The handles are successfully installed on the image. Otherwise
61 return EfiLibInstallDriverBindingComponentName2 (
64 &gMtftp4DriverBinding
,
66 &gMtftp4ComponentName
,
67 &gMtftp4ComponentName2
73 Test whether MTFTP driver support this controller.
75 @param This The MTFTP driver binding instance
76 @param Controller The controller to test
77 @param RemainingDevicePath The remaining device path
79 @retval EFI_SUCCESS The controller has UDP service binding protocol
80 installed, MTFTP can support it.
81 @retval Others MTFTP can't support the controller.
85 Mtftp4DriverBindingSupported (
86 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
87 IN EFI_HANDLE Controller
,
88 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
93 Status
= gBS
->OpenProtocol (
95 &gEfiUdp4ServiceBindingProtocolGuid
,
97 This
->DriverBindingHandle
,
99 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
107 Config a NULL UDP that is used to keep the connection between UDP
108 and MTFTP. Just leave the Udp child unconfigured. When UDP is
109 unloaded, MTFTP will be informed with DriverBinding Stop.
111 @param UdpIo The UDP port to configure
112 @param Context The opaque parameter to the callback
114 @retval EFI_SUCCESS It always return EFI_SUCCESS directly.
118 Mtftp4ConfigNullUdp (
119 IN UDP_IO_PORT
*UdpIo
,
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
)) {
184 gBS
->FreePool (MtftpSb
);
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
);
201 gBS
->FreePool (MtftpSb
);
205 MtftpSb
->ConnectUdp
= UdpIoCreatePort (Controller
, Image
, Mtftp4ConfigNullUdp
, NULL
);
207 if (MtftpSb
->ConnectUdp
== NULL
) {
208 gBS
->CloseEvent (MtftpSb
->TimerToGetMap
);
209 gBS
->CloseEvent (MtftpSb
->Timer
);
210 gBS
->FreePool (MtftpSb
);
211 return EFI_DEVICE_ERROR
;
220 Release all the resource used the MTFTP service binding instance.
222 @param MtftpSb The MTFTP service binding instance.
229 IN MTFTP4_SERVICE
*MtftpSb
232 UdpIoFreePort (MtftpSb
->ConnectUdp
);
233 gBS
->CloseEvent (MtftpSb
->TimerToGetMap
);
234 gBS
->CloseEvent (MtftpSb
->Timer
);
239 Start the MTFTP driver on this controller. MTFTP driver will
240 install a MTFTP SERVICE BINDING protocol on the supported
241 controller, which can be used to create/destroy MTFTP children.
243 @param This The MTFTP driver binding protocol.
244 @param Controller The controller to manage.
245 @param RemainingDevicePath Remaining device path.
247 @retval EFI_ALREADY_STARTED The MTFTP service binding protocol has been
248 started on the controller.
249 @retval EFI_SUCCESS The MTFTP service binding is installed on the
254 Mtftp4DriverBindingStart (
255 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
256 IN EFI_HANDLE Controller
,
257 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
260 MTFTP4_SERVICE
*MtftpSb
;
264 // Directly return if driver is already running.
266 Status
= gBS
->OpenProtocol (
268 &gEfiMtftp4ServiceBindingProtocolGuid
,
270 This
->DriverBindingHandle
,
272 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
275 if (Status
== EFI_SUCCESS
) {
276 return EFI_ALREADY_STARTED
;
279 Status
= Mtftp4CreateService (Controller
, This
->DriverBindingHandle
, &MtftpSb
);
281 if (EFI_ERROR (Status
)) {
285 Status
= gBS
->SetTimer (MtftpSb
->Timer
, TimerPeriodic
, TICKS_PER_SECOND
);
287 if (EFI_ERROR (Status
)) {
292 // Install the Mtftp4ServiceBinding Protocol onto Controller
294 Status
= gBS
->InstallMultipleProtocolInterfaces (
296 &gEfiMtftp4ServiceBindingProtocolGuid
,
297 &MtftpSb
->ServiceBinding
,
301 if (EFI_ERROR (Status
)) {
308 Mtftp4CleanService (MtftpSb
);
309 gBS
->FreePool (MtftpSb
);
316 Stop the MTFTP driver on controller. The controller is a UDP
319 @param This The MTFTP driver binding protocol
320 @param Controller The controller to stop
321 @param NumberOfChildren The number of children
322 @param ChildHandleBuffer The array of the child handle.
324 @retval EFI_SUCCESS The driver is stopped on the controller.
325 @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.
416 IN MTFTP4_SERVICE
*MtftpSb
,
417 IN MTFTP4_PROTOCOL
*Instance
420 ZeroMem (Instance
, sizeof (MTFTP4_PROTOCOL
));
422 Instance
->Signature
= MTFTP4_PROTOCOL_SIGNATURE
;
423 InitializeListHead (&Instance
->Link
);
424 CopyMem (&Instance
->Mtftp4
, &gMtftp4ProtocolTemplate
, sizeof (Instance
->Mtftp4
));
425 Instance
->State
= MTFTP4_STATE_UNCONFIGED
;
426 Instance
->Indestory
= FALSE
;
427 Instance
->Service
= MtftpSb
;
429 InitializeListHead (&Instance
->Blocks
);
434 Create a MTFTP child for the service binding instance, then
435 install the MTFTP protocol to the ChildHandle.
437 @param This The MTFTP service binding instance.
438 @param ChildHandle The Child handle to install the MTFTP protocol.
440 @retval EFI_INVALID_PARAMETER The parameter is invalid.
441 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the new child.
442 @retval EFI_SUCCESS The child is successfully create.
446 Mtftp4ServiceBindingCreateChild (
447 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
448 IN OUT EFI_HANDLE
*ChildHandle
451 MTFTP4_SERVICE
*MtftpSb
;
452 MTFTP4_PROTOCOL
*Instance
;
457 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
458 return EFI_INVALID_PARAMETER
;
461 Instance
= AllocatePool (sizeof (*Instance
));
463 if (Instance
== NULL
) {
464 return EFI_OUT_OF_RESOURCES
;
467 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (This
);
469 Mtftp4InitProtocol (MtftpSb
, Instance
);
471 Instance
->UnicastPort
= UdpIoCreatePort (
478 if (Instance
->UnicastPort
== NULL
) {
479 gBS
->FreePool (Instance
);
480 return EFI_OUT_OF_RESOURCES
;
484 // Install the MTFTP protocol onto ChildHandle
486 Status
= gBS
->InstallMultipleProtocolInterfaces (
488 &gEfiMtftp4ProtocolGuid
,
493 if (EFI_ERROR (Status
)) {
497 Instance
->Handle
= *ChildHandle
;
500 // Open the Udp4 protocol BY_CHILD.
502 Status
= gBS
->OpenProtocol (
503 MtftpSb
->ConnectUdp
->UdpHandle
,
504 &gEfiUdp4ProtocolGuid
,
506 gMtftp4DriverBinding
.DriverBindingHandle
,
508 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
510 if (EFI_ERROR (Status
)) {
511 gBS
->UninstallMultipleProtocolInterfaces (
513 &gEfiMtftp4ProtocolGuid
,
522 // Add it to the parent's child list.
524 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
526 InsertTailList (&MtftpSb
->Children
, &Instance
->Link
);
527 MtftpSb
->ChildrenNum
++;
529 gBS
->RestoreTPL (OldTpl
);
533 if (EFI_ERROR (Status
)) {
534 UdpIoFreePort (Instance
->UnicastPort
);
535 gBS
->FreePool (Instance
);
543 Destory one of the service binding's child.
545 @param This The service binding instance
546 @param ChildHandle The child handle to destory
548 @retval EFI_INVALID_PARAMETER The parameter is invaid.
549 @retval EFI_UNSUPPORTED The child may have already been destoried.
550 @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
);