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
37 //@MT: EFI_DRIVER_ENTRY_POINT (Mtftp4DriverEntryPoint)
41 Mtftp4DriverEntryPoint (
42 IN EFI_HANDLE ImageHandle
,
43 IN EFI_SYSTEM_TABLE
*SystemTable
49 The driver entry point which installs multiple protocols to the ImageHandle.
53 ImageHandle - The MTFTP's image handle
54 SystemTable - The system table
58 EFI_SUCCESS - The handles are successfully installed on the image. Otherwise
63 return NetLibInstallAllDriverProtocols (
66 &gMtftp4DriverBinding
,
68 &gMtftp4ComponentName
,
76 Test whether MTFTP driver support this controller.
78 @param This The MTFTP driver binding instance
79 @param Controller The controller to test
80 @param RemainingDevicePath The remaining device path
82 @retval EFI_SUCCESS The controller has UDP service binding protocol
83 installed, MTFTP can support it.
84 @retval Others MTFTP can't support the controller.
88 Mtftp4DriverBindingSupported (
89 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
90 IN EFI_HANDLE Controller
,
91 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
96 Status
= gBS
->OpenProtocol (
98 &gEfiUdp4ServiceBindingProtocolGuid
,
100 This
->DriverBindingHandle
,
102 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
110 Config a NULL UDP that is used to keep the connection between UDP
111 and MTFTP. Just leave the Udp child unconfigured. When UDP is
112 unloaded, MTFTP will be informed with DriverBinding Stop.
114 @param UdpIo The UDP port to configure
115 @param Context The opaque parameter to the callback
117 @retval EFI_SUCCESS It always return EFI_SUCCESS directly.
121 Mtftp4ConfigNullUdp (
122 IN UDP_IO_PORT
*UdpIo
,
131 Create then initialize a MTFTP service binding instance.
133 @param Controller The controller to install the MTFTP service
135 @param Image The driver binding image of the MTFTP driver
136 @param Service The variable to receive the created service
139 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance
140 @retval EFI_DEVICE_ERROR Failed to create a NULL UDP port to keep
142 @retval EFI_SUCCESS The service instance is created for the
147 Mtftp4CreateService (
148 IN EFI_HANDLE Controller
,
150 OUT MTFTP4_SERVICE
**Service
153 MTFTP4_SERVICE
*MtftpSb
;
157 MtftpSb
= NetAllocatePool (sizeof (MTFTP4_SERVICE
));
159 if (MtftpSb
== NULL
) {
160 return EFI_OUT_OF_RESOURCES
;
163 MtftpSb
->Signature
= MTFTP4_SERVICE_SIGNATURE
;
164 MtftpSb
->ServiceBinding
= gMtftp4ServiceBindingTemplete
;
165 MtftpSb
->InDestory
= FALSE
;
166 MtftpSb
->ChildrenNum
= 0;
167 NetListInit (&MtftpSb
->Children
);
169 MtftpSb
->Timer
= NULL
;
170 MtftpSb
->TimerToGetMap
= NULL
;
171 MtftpSb
->Controller
= Controller
;
172 MtftpSb
->Image
= Image
;
173 MtftpSb
->ConnectUdp
= NULL
;
176 // Create the timer and a udp to be notified when UDP is uninstalled
178 Status
= gBS
->CreateEvent (
179 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
186 if (EFI_ERROR (Status
)) {
187 NetFreePool (MtftpSb
);
192 // Create the timer used to time out the procedure which is used to
193 // get the default IP address.
195 Status
= gBS
->CreateEvent (
200 &MtftpSb
->TimerToGetMap
202 if (EFI_ERROR (Status
)) {
203 gBS
->CloseEvent (MtftpSb
->Timer
);
204 NetFreePool (MtftpSb
);
208 MtftpSb
->ConnectUdp
= UdpIoCreatePort (Controller
, Image
, Mtftp4ConfigNullUdp
, NULL
);
210 if (MtftpSb
->ConnectUdp
== NULL
) {
211 gBS
->CloseEvent (MtftpSb
->TimerToGetMap
);
212 gBS
->CloseEvent (MtftpSb
->Timer
);
213 NetFreePool (MtftpSb
);
214 return EFI_DEVICE_ERROR
;
223 Release all the resource used the MTFTP service binding instance.
225 @param MtftpSb The MTFTP service binding instance.
232 IN MTFTP4_SERVICE
*MtftpSb
235 UdpIoFreePort (MtftpSb
->ConnectUdp
);
236 gBS
->CloseEvent (MtftpSb
->TimerToGetMap
);
237 gBS
->CloseEvent (MtftpSb
->Timer
);
242 Start the MTFTP driver on this controller. MTFTP driver will
243 install a MTFTP SERVICE BINDING protocol on the supported
244 controller, which can be used to create/destroy MTFTP children.
246 @param This The MTFTP driver binding protocol.
247 @param Controller The controller to manage.
248 @param RemainingDevicePath Remaining device path.
250 @retval EFI_ALREADY_STARTED The MTFTP service binding protocol has been
251 started on the controller.
252 @retval EFI_SUCCESS The MTFTP service binding is installed on the
257 Mtftp4DriverBindingStart (
258 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
259 IN EFI_HANDLE Controller
,
260 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
263 MTFTP4_SERVICE
*MtftpSb
;
267 // Directly return if driver is already running.
269 Status
= gBS
->OpenProtocol (
271 &gEfiMtftp4ServiceBindingProtocolGuid
,
273 This
->DriverBindingHandle
,
275 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
278 if (Status
== EFI_SUCCESS
) {
279 return EFI_ALREADY_STARTED
;
282 Status
= Mtftp4CreateService (Controller
, This
->DriverBindingHandle
, &MtftpSb
);
284 if (EFI_ERROR (Status
)) {
288 Status
= gBS
->SetTimer (MtftpSb
->Timer
, TimerPeriodic
, TICKS_PER_SECOND
);
290 if (EFI_ERROR (Status
)) {
295 // Install the Mtftp4ServiceBinding Protocol onto Controller
297 Status
= gBS
->InstallMultipleProtocolInterfaces (
299 &gEfiMtftp4ServiceBindingProtocolGuid
,
300 &MtftpSb
->ServiceBinding
,
304 if (EFI_ERROR (Status
)) {
311 Mtftp4CleanService (MtftpSb
);
312 NetFreePool (MtftpSb
);
319 Stop the MTFTP driver on controller. The controller is a UDP
322 @param This The MTFTP driver binding protocol
323 @param Controller The controller to stop
324 @param NumberOfChildren The number of children
325 @param ChildHandleBuffer The array of the child handle.
327 @retval EFI_SUCCESS The driver is stopped on the controller.
328 @retval EFI_DEVICE_ERROR Failed to stop the driver on the controller.
332 Mtftp4DriverBindingStop (
333 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
334 IN EFI_HANDLE Controller
,
335 IN UINTN NumberOfChildren
,
336 IN EFI_HANDLE
*ChildHandleBuffer
339 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
340 MTFTP4_SERVICE
*MtftpSb
;
341 MTFTP4_PROTOCOL
*Instance
;
342 EFI_HANDLE NicHandle
;
347 // MTFTP driver opens UDP child, So, Controller is a UDP
348 // child handle. Locate the Nic handle first. Then get the
349 // MTFTP private data back.
351 NicHandle
= NetLibGetNicHandle (Controller
, &gEfiUdp4ProtocolGuid
);
353 if (NicHandle
== NULL
) {
357 Status
= gBS
->OpenProtocol (
359 &gEfiMtftp4ServiceBindingProtocolGuid
,
360 (VOID
**) &ServiceBinding
,
361 This
->DriverBindingHandle
,
363 EFI_OPEN_PROTOCOL_GET_PROTOCOL
366 if (EFI_ERROR (Status
)) {
367 return EFI_DEVICE_ERROR
;
370 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (ServiceBinding
);
372 if (MtftpSb
->InDestory
) {
376 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
377 MtftpSb
->InDestory
= TRUE
;
379 while (!NetListIsEmpty (&MtftpSb
->Children
)) {
380 Instance
= NET_LIST_HEAD (&MtftpSb
->Children
, MTFTP4_PROTOCOL
, Link
);
381 Mtftp4ServiceBindingDestroyChild (ServiceBinding
, Instance
->Handle
);
384 if (MtftpSb
->ChildrenNum
!= 0) {
385 Status
= EFI_DEVICE_ERROR
;
389 Status
= gBS
->UninstallProtocolInterface (
391 &gEfiMtftp4ServiceBindingProtocolGuid
,
395 if (EFI_ERROR (Status
)) {
399 Mtftp4CleanService (MtftpSb
);
400 NetFreePool (MtftpSb
);
402 NET_RESTORE_TPL (OldTpl
);
406 MtftpSb
->InDestory
= FALSE
;
408 NET_RESTORE_TPL (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.
424 IN MTFTP4_SERVICE
*MtftpSb
,
425 IN MTFTP4_PROTOCOL
*Instance
428 NetZeroMem (Instance
, sizeof (MTFTP4_PROTOCOL
));
430 Instance
->Signature
= MTFTP4_PROTOCOL_SIGNATURE
;
431 NetListInit (&Instance
->Link
);
432 CopyMem (&Instance
->Mtftp4
, &gMtftp4ProtocolTemplate
, sizeof (EFI_MTFTP4_PROTOCOL
));
433 Instance
->State
= MTFTP4_STATE_UNCONFIGED
;
434 Instance
->Indestory
= FALSE
;
435 Instance
->Service
= MtftpSb
;
437 NetListInit (&Instance
->Blocks
);
442 Create a MTFTP child for the service binding instance, then
443 install the MTFTP protocol to the ChildHandle.
445 @param This The MTFTP service binding instance.
446 @param ChildHandle The Child handle to install the MTFTP protocol.
448 @retval EFI_INVALID_PARAMETER The parameter is invalid.
449 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the new child.
450 @retval EFI_SUCCESS The child is successfully create.
454 Mtftp4ServiceBindingCreateChild (
455 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
456 IN OUT EFI_HANDLE
*ChildHandle
459 MTFTP4_SERVICE
*MtftpSb
;
460 MTFTP4_PROTOCOL
*Instance
;
465 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
466 return EFI_INVALID_PARAMETER
;
469 Instance
= NetAllocatePool (sizeof (*Instance
));
471 if (Instance
== NULL
) {
472 return EFI_OUT_OF_RESOURCES
;
475 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (This
);
477 Mtftp4InitProtocol (MtftpSb
, Instance
);
479 Instance
->UnicastPort
= UdpIoCreatePort (
486 if (Instance
->UnicastPort
== NULL
) {
487 NetFreePool (Instance
);
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
= NET_RAISE_TPL (NET_TPL_LOCK
);
534 NetListInsertTail (&MtftpSb
->Children
, &Instance
->Link
);
535 MtftpSb
->ChildrenNum
++;
537 NET_RESTORE_TPL (OldTpl
);
541 if (EFI_ERROR (Status
)) {
542 UdpIoFreePort (Instance
->UnicastPort
);
543 NetFreePool (Instance
);
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
563 Mtftp4ServiceBindingDestroyChild (
564 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
565 IN EFI_HANDLE ChildHandle
568 MTFTP4_SERVICE
*MtftpSb
;
569 MTFTP4_PROTOCOL
*Instance
;
570 EFI_MTFTP4_PROTOCOL
*Mtftp4
;
574 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
575 return EFI_INVALID_PARAMETER
;
579 // Retrieve the private context data structures
581 Status
= gBS
->OpenProtocol (
583 &gEfiMtftp4ProtocolGuid
,
585 gMtftp4DriverBinding
.DriverBindingHandle
,
587 EFI_OPEN_PROTOCOL_GET_PROTOCOL
590 if (EFI_ERROR (Status
)) {
591 return EFI_UNSUPPORTED
;
594 Instance
= MTFTP4_PROTOCOL_FROM_THIS (Mtftp4
);
595 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (This
);
597 if (Instance
->Service
!= MtftpSb
) {
598 return EFI_INVALID_PARAMETER
;
601 if (Instance
->Indestory
) {
605 Instance
->Indestory
= TRUE
;
608 // Close the Udp4 protocol.
611 MtftpSb
->ConnectUdp
->UdpHandle
,
612 &gEfiUdp4ProtocolGuid
,
613 gMtftp4DriverBinding
.DriverBindingHandle
,
618 // Uninstall the MTFTP4 protocol first to enable a top down destruction.
620 Status
= gBS
->UninstallProtocolInterface (
622 &gEfiMtftp4ProtocolGuid
,
626 if (EFI_ERROR (Status
)) {
627 Instance
->Indestory
= FALSE
;
631 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
633 Mtftp4CleanOperation (Instance
, EFI_DEVICE_ERROR
);
634 UdpIoFreePort (Instance
->UnicastPort
);
636 NetListRemoveEntry (&Instance
->Link
);
637 MtftpSb
->ChildrenNum
--;
639 NET_RESTORE_TPL (OldTpl
);
641 NetFreePool (Instance
);