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 NetLibInstallAllDriverProtocols (
64 &gMtftp4DriverBinding
,
66 &gMtftp4ComponentName
,
74 Test whether MTFTP driver support this controller.
76 @param This The MTFTP driver binding instance
77 @param Controller The controller to test
78 @param RemainingDevicePath The remaining device path
80 @retval EFI_SUCCESS The controller has UDP service binding protocol
81 installed, MTFTP can support it.
82 @retval Others MTFTP can't support the controller.
86 Mtftp4DriverBindingSupported (
87 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
88 IN EFI_HANDLE Controller
,
89 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
94 Status
= gBS
->OpenProtocol (
96 &gEfiUdp4ServiceBindingProtocolGuid
,
98 This
->DriverBindingHandle
,
100 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
108 Config a NULL UDP that is used to keep the connection between UDP
109 and MTFTP. Just leave the Udp child unconfigured. When UDP is
110 unloaded, MTFTP will be informed with DriverBinding Stop.
112 @param UdpIo The UDP port to configure
113 @param Context The opaque parameter to the callback
115 @retval EFI_SUCCESS It always return EFI_SUCCESS directly.
119 Mtftp4ConfigNullUdp (
120 IN UDP_IO_PORT
*UdpIo
,
129 Create then initialize a MTFTP service binding instance.
131 @param Controller The controller to install the MTFTP service
133 @param Image The driver binding image of the MTFTP driver
134 @param Service The variable to receive the created service
137 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance
138 @retval EFI_DEVICE_ERROR Failed to create a NULL UDP port to keep
140 @retval EFI_SUCCESS The service instance is created for the
145 Mtftp4CreateService (
146 IN EFI_HANDLE Controller
,
148 OUT MTFTP4_SERVICE
**Service
151 MTFTP4_SERVICE
*MtftpSb
;
155 MtftpSb
= NetAllocatePool (sizeof (MTFTP4_SERVICE
));
157 if (MtftpSb
== NULL
) {
158 return EFI_OUT_OF_RESOURCES
;
161 MtftpSb
->Signature
= MTFTP4_SERVICE_SIGNATURE
;
162 MtftpSb
->ServiceBinding
= gMtftp4ServiceBindingTemplete
;
163 MtftpSb
->InDestory
= FALSE
;
164 MtftpSb
->ChildrenNum
= 0;
165 NetListInit (&MtftpSb
->Children
);
167 MtftpSb
->Timer
= NULL
;
168 MtftpSb
->TimerToGetMap
= NULL
;
169 MtftpSb
->Controller
= Controller
;
170 MtftpSb
->Image
= Image
;
171 MtftpSb
->ConnectUdp
= NULL
;
174 // Create the timer and a udp to be notified when UDP is uninstalled
176 Status
= gBS
->CreateEvent (
177 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
184 if (EFI_ERROR (Status
)) {
185 NetFreePool (MtftpSb
);
190 // Create the timer used to time out the procedure which is used to
191 // get the default IP address.
193 Status
= gBS
->CreateEvent (
198 &MtftpSb
->TimerToGetMap
200 if (EFI_ERROR (Status
)) {
201 gBS
->CloseEvent (MtftpSb
->Timer
);
202 NetFreePool (MtftpSb
);
206 MtftpSb
->ConnectUdp
= UdpIoCreatePort (Controller
, Image
, Mtftp4ConfigNullUdp
, NULL
);
208 if (MtftpSb
->ConnectUdp
== NULL
) {
209 gBS
->CloseEvent (MtftpSb
->TimerToGetMap
);
210 gBS
->CloseEvent (MtftpSb
->Timer
);
211 NetFreePool (MtftpSb
);
212 return EFI_DEVICE_ERROR
;
221 Release all the resource used the MTFTP service binding instance.
223 @param MtftpSb The MTFTP service binding instance.
230 IN MTFTP4_SERVICE
*MtftpSb
233 UdpIoFreePort (MtftpSb
->ConnectUdp
);
234 gBS
->CloseEvent (MtftpSb
->TimerToGetMap
);
235 gBS
->CloseEvent (MtftpSb
->Timer
);
240 Start the MTFTP driver on this controller. MTFTP driver will
241 install a MTFTP SERVICE BINDING protocol on the supported
242 controller, which can be used to create/destroy MTFTP children.
244 @param This The MTFTP driver binding protocol.
245 @param Controller The controller to manage.
246 @param RemainingDevicePath Remaining device path.
248 @retval EFI_ALREADY_STARTED The MTFTP service binding protocol has been
249 started on the controller.
250 @retval EFI_SUCCESS The MTFTP service binding is installed on the
255 Mtftp4DriverBindingStart (
256 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
257 IN EFI_HANDLE Controller
,
258 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
261 MTFTP4_SERVICE
*MtftpSb
;
265 // Directly return if driver is already running.
267 Status
= gBS
->OpenProtocol (
269 &gEfiMtftp4ServiceBindingProtocolGuid
,
271 This
->DriverBindingHandle
,
273 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
276 if (Status
== EFI_SUCCESS
) {
277 return EFI_ALREADY_STARTED
;
280 Status
= Mtftp4CreateService (Controller
, This
->DriverBindingHandle
, &MtftpSb
);
282 if (EFI_ERROR (Status
)) {
286 Status
= gBS
->SetTimer (MtftpSb
->Timer
, TimerPeriodic
, TICKS_PER_SECOND
);
288 if (EFI_ERROR (Status
)) {
293 // Install the Mtftp4ServiceBinding Protocol onto Controller
295 Status
= gBS
->InstallMultipleProtocolInterfaces (
297 &gEfiMtftp4ServiceBindingProtocolGuid
,
298 &MtftpSb
->ServiceBinding
,
302 if (EFI_ERROR (Status
)) {
309 Mtftp4CleanService (MtftpSb
);
310 NetFreePool (MtftpSb
);
317 Stop the MTFTP driver on controller. The controller is a UDP
320 @param This The MTFTP driver binding protocol
321 @param Controller The controller to stop
322 @param NumberOfChildren The number of children
323 @param ChildHandleBuffer The array of the child handle.
325 @retval EFI_SUCCESS The driver is stopped on the controller.
326 @retval EFI_DEVICE_ERROR Failed to stop the driver on the controller.
330 Mtftp4DriverBindingStop (
331 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
332 IN EFI_HANDLE Controller
,
333 IN UINTN NumberOfChildren
,
334 IN EFI_HANDLE
*ChildHandleBuffer
337 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
338 MTFTP4_SERVICE
*MtftpSb
;
339 MTFTP4_PROTOCOL
*Instance
;
340 EFI_HANDLE NicHandle
;
345 // MTFTP driver opens UDP child, So, Controller is a UDP
346 // child handle. Locate the Nic handle first. Then get the
347 // MTFTP private data back.
349 NicHandle
= NetLibGetNicHandle (Controller
, &gEfiUdp4ProtocolGuid
);
351 if (NicHandle
== NULL
) {
355 Status
= gBS
->OpenProtocol (
357 &gEfiMtftp4ServiceBindingProtocolGuid
,
358 (VOID
**) &ServiceBinding
,
359 This
->DriverBindingHandle
,
361 EFI_OPEN_PROTOCOL_GET_PROTOCOL
364 if (EFI_ERROR (Status
)) {
365 return EFI_DEVICE_ERROR
;
368 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (ServiceBinding
);
370 if (MtftpSb
->InDestory
) {
374 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
375 MtftpSb
->InDestory
= TRUE
;
377 while (!NetListIsEmpty (&MtftpSb
->Children
)) {
378 Instance
= NET_LIST_HEAD (&MtftpSb
->Children
, MTFTP4_PROTOCOL
, Link
);
379 Mtftp4ServiceBindingDestroyChild (ServiceBinding
, Instance
->Handle
);
382 if (MtftpSb
->ChildrenNum
!= 0) {
383 Status
= EFI_DEVICE_ERROR
;
387 Status
= gBS
->UninstallProtocolInterface (
389 &gEfiMtftp4ServiceBindingProtocolGuid
,
393 if (EFI_ERROR (Status
)) {
397 Mtftp4CleanService (MtftpSb
);
398 NetFreePool (MtftpSb
);
400 NET_RESTORE_TPL (OldTpl
);
404 MtftpSb
->InDestory
= FALSE
;
406 NET_RESTORE_TPL (OldTpl
);
412 Initialize a MTFTP protocol instance which is the child of MtftpSb.
414 @param MtftpSb The MTFTP service binding protocol.
415 @param Instance The MTFTP instance to initialize.
422 IN MTFTP4_SERVICE
*MtftpSb
,
423 IN MTFTP4_PROTOCOL
*Instance
426 NetZeroMem (Instance
, sizeof (MTFTP4_PROTOCOL
));
428 Instance
->Signature
= MTFTP4_PROTOCOL_SIGNATURE
;
429 NetListInit (&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 NetListInit (&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.
452 Mtftp4ServiceBindingCreateChild (
453 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
454 IN OUT EFI_HANDLE
*ChildHandle
457 MTFTP4_SERVICE
*MtftpSb
;
458 MTFTP4_PROTOCOL
*Instance
;
463 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
464 return EFI_INVALID_PARAMETER
;
467 Instance
= NetAllocatePool (sizeof (*Instance
));
469 if (Instance
== NULL
) {
470 return EFI_OUT_OF_RESOURCES
;
473 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (This
);
475 Mtftp4InitProtocol (MtftpSb
, Instance
);
477 Instance
->UnicastPort
= UdpIoCreatePort (
484 if (Instance
->UnicastPort
== NULL
) {
485 NetFreePool (Instance
);
486 return EFI_OUT_OF_RESOURCES
;
490 // Install the MTFTP protocol onto ChildHandle
492 Status
= gBS
->InstallMultipleProtocolInterfaces (
494 &gEfiMtftp4ProtocolGuid
,
499 if (EFI_ERROR (Status
)) {
503 Instance
->Handle
= *ChildHandle
;
506 // Open the Udp4 protocol BY_CHILD.
508 Status
= gBS
->OpenProtocol (
509 MtftpSb
->ConnectUdp
->UdpHandle
,
510 &gEfiUdp4ProtocolGuid
,
512 gMtftp4DriverBinding
.DriverBindingHandle
,
514 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
516 if (EFI_ERROR (Status
)) {
517 gBS
->UninstallMultipleProtocolInterfaces (
519 &gEfiMtftp4ProtocolGuid
,
528 // Add it to the parent's child list.
530 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
532 NetListInsertTail (&MtftpSb
->Children
, &Instance
->Link
);
533 MtftpSb
->ChildrenNum
++;
535 NET_RESTORE_TPL (OldTpl
);
539 if (EFI_ERROR (Status
)) {
540 UdpIoFreePort (Instance
->UnicastPort
);
541 NetFreePool (Instance
);
549 Destory one of the service binding's child.
551 @param This The service binding instance
552 @param ChildHandle The child handle to destory
554 @retval EFI_INVALID_PARAMETER The parameter is invaid.
555 @retval EFI_UNSUPPORTED The child may have already been destoried.
556 @retval EFI_SUCCESS The child is destoried and removed from the
561 Mtftp4ServiceBindingDestroyChild (
562 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
563 IN EFI_HANDLE ChildHandle
566 MTFTP4_SERVICE
*MtftpSb
;
567 MTFTP4_PROTOCOL
*Instance
;
568 EFI_MTFTP4_PROTOCOL
*Mtftp4
;
572 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
573 return EFI_INVALID_PARAMETER
;
577 // Retrieve the private context data structures
579 Status
= gBS
->OpenProtocol (
581 &gEfiMtftp4ProtocolGuid
,
583 gMtftp4DriverBinding
.DriverBindingHandle
,
585 EFI_OPEN_PROTOCOL_GET_PROTOCOL
588 if (EFI_ERROR (Status
)) {
589 return EFI_UNSUPPORTED
;
592 Instance
= MTFTP4_PROTOCOL_FROM_THIS (Mtftp4
);
593 MtftpSb
= MTFTP4_SERVICE_FROM_THIS (This
);
595 if (Instance
->Service
!= MtftpSb
) {
596 return EFI_INVALID_PARAMETER
;
599 if (Instance
->Indestory
) {
603 Instance
->Indestory
= TRUE
;
606 // Close the Udp4 protocol.
609 MtftpSb
->ConnectUdp
->UdpHandle
,
610 &gEfiUdp4ProtocolGuid
,
611 gMtftp4DriverBinding
.DriverBindingHandle
,
616 // Uninstall the MTFTP4 protocol first to enable a top down destruction.
618 Status
= gBS
->UninstallProtocolInterface (
620 &gEfiMtftp4ProtocolGuid
,
624 if (EFI_ERROR (Status
)) {
625 Instance
->Indestory
= FALSE
;
629 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
631 Mtftp4CleanOperation (Instance
, EFI_DEVICE_ERROR
);
632 UdpIoFreePort (Instance
->UnicastPort
);
634 NetListRemoveEntry (&Instance
->Link
);
635 MtftpSb
->ChildrenNum
--;
637 NET_RESTORE_TPL (OldTpl
);
639 NetFreePool (Instance
);