TianoCore EDK2 master
Loading...
Searching...
No Matches
Mtftp6Driver.c
Go to the documentation of this file.
1
11#include "Mtftp6Impl.h"
12
13EFI_DRIVER_BINDING_PROTOCOL gMtftp6DriverBinding = {
17 0xa,
18 NULL,
19 NULL
20};
21
22EFI_SERVICE_BINDING_PROTOCOL gMtftp6ServiceBindingTemplate = {
25};
26
35VOID
37 IN MTFTP6_SERVICE *Service
38 )
39{
40 //
41 // Make sure all children instances have been already destroyed.
42 //
43 ASSERT (Service->ChildrenNum == 0);
44
45 if (Service->DummyUdpIo != NULL) {
46 UdpIoFreeIo (Service->DummyUdpIo);
47 }
48
49 if (Service->Timer != NULL) {
50 gBS->CloseEvent (Service->Timer);
51 }
52
53 FreePool (Service);
54}
55
72 IN EFI_HANDLE Controller,
73 IN EFI_HANDLE Image,
74 OUT MTFTP6_SERVICE **Service
75 )
76{
77 MTFTP6_SERVICE *Mtftp6Srv;
78 EFI_STATUS Status;
79
80 ASSERT (Service != NULL);
81
82 *Service = NULL;
83 Mtftp6Srv = AllocateZeroPool (sizeof (MTFTP6_SERVICE));
84
85 if (Mtftp6Srv == NULL) {
86 return EFI_OUT_OF_RESOURCES;
87 }
88
89 Mtftp6Srv->Signature = MTFTP6_SERVICE_SIGNATURE;
90 Mtftp6Srv->Controller = Controller;
91 Mtftp6Srv->Image = Image;
92 Mtftp6Srv->ChildrenNum = 0;
93
94 CopyMem (
95 &Mtftp6Srv->ServiceBinding,
96 &gMtftp6ServiceBindingTemplate,
98 );
99
100 InitializeListHead (&Mtftp6Srv->Children);
101
102 //
103 // Create a internal timer for all instances.
104 //
105 Status = gBS->CreateEvent (
106 EVT_NOTIFY_SIGNAL | EVT_TIMER,
107 TPL_CALLBACK,
109 Mtftp6Srv,
110 &Mtftp6Srv->Timer
111 );
112
113 if (EFI_ERROR (Status)) {
114 FreePool (Mtftp6Srv);
115 return Status;
116 }
117
118 //
119 // Create a dummy Udp6Io to build parent-child relationship between Udp6 driver
120 // and Mtftp6 driver.
121 //
122 Mtftp6Srv->DummyUdpIo = UdpIoCreateIo (
123 Controller,
124 Image,
126 UDP_IO_UDP6_VERSION,
127 NULL
128 );
129
130 if (Mtftp6Srv->DummyUdpIo == NULL) {
131 gBS->CloseEvent (Mtftp6Srv->Timer);
132 FreePool (Mtftp6Srv);
133 return EFI_DEVICE_ERROR;
134 }
135
136 *Service = Mtftp6Srv;
137 return EFI_SUCCESS;
138}
139
146VOID
148 IN MTFTP6_INSTANCE *Instance
149 )
150{
151 LIST_ENTRY *Entry;
152 LIST_ENTRY *Next;
153 MTFTP6_BLOCK_RANGE *Block;
154
155 if (Instance->Config != NULL) {
156 FreePool (Instance->Config);
157 }
158
159 if ((Instance->Token != NULL) && (Instance->Token->Event != NULL)) {
160 gBS->SignalEvent (Instance->Token->Event);
161 }
162
163 if (Instance->LastPacket != NULL) {
164 NetbufFree (Instance->LastPacket);
165 }
166
167 if (Instance->UdpIo != NULL) {
168 UdpIoFreeIo (Instance->UdpIo);
169 }
170
171 if (Instance->McastUdpIo != NULL) {
172 UdpIoFreeIo (Instance->McastUdpIo);
173 }
174
175 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Instance->BlkList) {
176 Block = NET_LIST_USER_STRUCT (Entry, MTFTP6_BLOCK_RANGE, Link);
177 RemoveEntryList (Entry);
178 FreePool (Block);
179 }
180
181 FreePool (Instance);
182}
183
196 IN MTFTP6_SERVICE *Service,
197 OUT MTFTP6_INSTANCE **Instance
198 )
199{
200 MTFTP6_INSTANCE *Mtftp6Ins;
201
202 *Instance = NULL;
203 Mtftp6Ins = AllocateZeroPool (sizeof (MTFTP6_INSTANCE));
204
205 if (Mtftp6Ins == NULL) {
206 return EFI_OUT_OF_RESOURCES;
207 }
208
209 Mtftp6Ins->Signature = MTFTP6_INSTANCE_SIGNATURE;
210 Mtftp6Ins->InDestroy = FALSE;
211 Mtftp6Ins->Service = Service;
212
213 CopyMem (
214 &Mtftp6Ins->Mtftp6,
215 &gMtftp6ProtocolTemplate,
216 sizeof (EFI_MTFTP6_PROTOCOL)
217 );
218
219 InitializeListHead (&Mtftp6Ins->Link);
220 InitializeListHead (&Mtftp6Ins->BlkList);
221
222 *Instance = Mtftp6Ins;
223
224 return EFI_SUCCESS;
225}
226
238EFIAPI
240 IN LIST_ENTRY *Entry,
241 IN VOID *Context
242 )
243{
244 MTFTP6_INSTANCE *Instance;
245 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
246 UINTN NumberOfChildren;
247 EFI_HANDLE *ChildHandleBuffer;
248
249 if ((Entry == NULL) || (Context == NULL)) {
250 return EFI_INVALID_PARAMETER;
251 }
252
253 Instance = NET_LIST_USER_STRUCT_S (Entry, MTFTP6_INSTANCE, Link, MTFTP6_INSTANCE_SIGNATURE);
254 ServiceBinding = ((MTFTP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *)Context)->ServiceBinding;
255 NumberOfChildren = ((MTFTP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *)Context)->NumberOfChildren;
256 ChildHandleBuffer = ((MTFTP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *)Context)->ChildHandleBuffer;
257
258 if (!NetIsInHandleBuffer (Instance->Handle, NumberOfChildren, ChildHandleBuffer)) {
259 return EFI_SUCCESS;
260 }
261
262 return ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);
263}
264
280EFIAPI
282 IN EFI_HANDLE ImageHandle,
283 IN EFI_SYSTEM_TABLE *SystemTable
284 )
285{
287 ImageHandle,
288 SystemTable,
289 &gMtftp6DriverBinding,
290 ImageHandle,
291 &gMtftp6ComponentName,
292 &gMtftp6ComponentName2
293 );
294}
295
314EFIAPI
317 IN EFI_HANDLE Controller,
318 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
319 )
320{
321 return gBS->OpenProtocol (
322 Controller,
323 &gEfiUdp6ServiceBindingProtocolGuid,
324 NULL,
325 This->DriverBindingHandle,
326 Controller,
327 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
328 );
329}
330
350EFIAPI
353 IN EFI_HANDLE Controller,
354 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
355 )
356{
357 MTFTP6_SERVICE *Service;
358 EFI_STATUS Status;
359
360 //
361 // Directly return if driver is already running on this Nic handle.
362 //
363 Status = gBS->OpenProtocol (
364 Controller,
365 &gEfiMtftp6ServiceBindingProtocolGuid,
366 NULL,
367 This->DriverBindingHandle,
368 Controller,
369 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
370 );
371
372 if (!EFI_ERROR (Status)) {
373 return EFI_ALREADY_STARTED;
374 }
375
376 //
377 // Create Mtftp6 service for this Nic handle
378 //
379 Status = Mtftp6CreateService (
380 Controller,
381 This->DriverBindingHandle,
382 &Service
383 );
384
385 if (EFI_ERROR (Status)) {
386 return Status;
387 }
388
389 ASSERT (Service != NULL);
390
391 //
392 // Start the internal timer to track the packet retransmission.
393 //
394 Status = gBS->SetTimer (
395 Service->Timer,
397 TICKS_PER_SECOND
398 );
399
400 if (EFI_ERROR (Status)) {
401 goto ON_ERROR;
402 }
403
404 //
405 // Install the Mtftp6 service on the Nic handle.
406 //
407 Status = gBS->InstallMultipleProtocolInterfaces (
408 &Controller,
409 &gEfiMtftp6ServiceBindingProtocolGuid,
410 &Service->ServiceBinding,
411 NULL
412 );
413
414 if (EFI_ERROR (Status)) {
415 goto ON_ERROR;
416 }
417
418 return EFI_SUCCESS;
419
420ON_ERROR:
421
422 Mtftp6DestroyService (Service);
423 return Status;
424}
425
446EFIAPI
449 IN EFI_HANDLE Controller,
450 IN UINTN NumberOfChildren,
451 IN EFI_HANDLE *ChildHandleBuffer
452 )
453{
454 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
455 MTFTP6_SERVICE *Service;
456 EFI_HANDLE NicHandle;
457 EFI_STATUS Status;
458 LIST_ENTRY *List;
460
461 //
462 // Locate the Nic handle to retrieve the Mtftp6 private data.
463 //
464 NicHandle = NetLibGetNicHandle (Controller, &gEfiUdp6ProtocolGuid);
465
466 if (NicHandle == NULL) {
467 return EFI_SUCCESS;
468 }
469
470 Status = gBS->OpenProtocol (
471 NicHandle,
472 &gEfiMtftp6ServiceBindingProtocolGuid,
473 (VOID **)&ServiceBinding,
474 This->DriverBindingHandle,
475 NicHandle,
476 EFI_OPEN_PROTOCOL_GET_PROTOCOL
477 );
478
479 if (EFI_ERROR (Status)) {
480 return EFI_DEVICE_ERROR;
481 }
482
483 Service = MTFTP6_SERVICE_FROM_THIS (ServiceBinding);
484
485 if (!IsListEmpty (&Service->Children)) {
486 //
487 // Destroy the Mtftp6 child instance in ChildHandleBuffer.
488 //
489 List = &Service->Children;
490 Context.ServiceBinding = ServiceBinding;
491 Context.NumberOfChildren = NumberOfChildren;
492 Context.ChildHandleBuffer = ChildHandleBuffer;
493 Status = NetDestroyLinkList (
494 List,
496 &Context,
497 NULL
498 );
499 }
500
501 if ((NumberOfChildren == 0) && IsListEmpty (&Service->Children)) {
502 //
503 // Destroy the Mtftp6 service if there is no Mtftp6 child instance left.
504 //
505 gBS->UninstallProtocolInterface (
506 NicHandle,
507 &gEfiMtftp6ServiceBindingProtocolGuid,
508 ServiceBinding
509 );
510
511 Mtftp6DestroyService (Service);
512 Status = EFI_SUCCESS;
513 }
514
515 return Status;
516}
517
536EFIAPI
539 IN OUT EFI_HANDLE *ChildHandle
540 )
541{
542 MTFTP6_SERVICE *Service;
543 MTFTP6_INSTANCE *Instance;
544 EFI_STATUS Status;
545 EFI_TPL OldTpl;
546 VOID *Udp6;
547
548 if ((This == NULL) || (ChildHandle == NULL)) {
549 return EFI_INVALID_PARAMETER;
550 }
551
552 Service = MTFTP6_SERVICE_FROM_THIS (This);
553
554 Status = Mtftp6CreateInstance (Service, &Instance);
555
556 if (EFI_ERROR (Status)) {
557 return Status;
558 }
559
560 ASSERT (Instance != NULL);
561
562 //
563 // Install the Mtftp6 protocol on the new child handle.
564 //
565 Status = gBS->InstallMultipleProtocolInterfaces (
566 ChildHandle,
567 &gEfiMtftp6ProtocolGuid,
568 &Instance->Mtftp6,
569 NULL
570 );
571
572 if (EFI_ERROR (Status)) {
573 goto ON_ERROR;
574 }
575
576 Instance->Handle = *ChildHandle;
577
578 //
579 // Open the Udp6 protocol by child.
580 //
581 Status = gBS->OpenProtocol (
582 Service->DummyUdpIo->UdpHandle,
583 &gEfiUdp6ProtocolGuid,
584 (VOID **)&Udp6,
585 gMtftp6DriverBinding.DriverBindingHandle,
586 Instance->Handle,
587 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
588 );
589
590 if (EFI_ERROR (Status)) {
591 gBS->UninstallMultipleProtocolInterfaces (
592 Instance->Handle,
593 &gEfiMtftp6ProtocolGuid,
594 &Instance->Mtftp6,
595 NULL
596 );
597
598 goto ON_ERROR;
599 }
600
601 //
602 // Add the new Mtftp6 instance into the children list of Mtftp6 service.
603 //
604 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
605
606 InsertTailList (&Service->Children, &Instance->Link);
607 Service->ChildrenNum++;
608
609 gBS->RestoreTPL (OldTpl);
610 return EFI_SUCCESS;
611
612ON_ERROR:
613
614 Mtftp6DestroyInstance (Instance);
615 return Status;
616}
617
635EFIAPI
638 IN EFI_HANDLE ChildHandle
639 )
640{
641 MTFTP6_SERVICE *Service;
642 MTFTP6_INSTANCE *Instance;
643 EFI_MTFTP6_PROTOCOL *Mtftp6;
644 EFI_STATUS Status;
645 EFI_TPL OldTpl;
646
647 if ((This == NULL) || (ChildHandle == NULL)) {
648 return EFI_INVALID_PARAMETER;
649 }
650
651 //
652 // Locate the Nic handle to retrieve the Mtftp6 private data.
653 //
654 Status = gBS->OpenProtocol (
655 ChildHandle,
656 &gEfiMtftp6ProtocolGuid,
657 (VOID **)&Mtftp6,
658 gMtftp6DriverBinding.DriverBindingHandle,
659 ChildHandle,
660 EFI_OPEN_PROTOCOL_GET_PROTOCOL
661 );
662
663 if (EFI_ERROR (Status)) {
664 return EFI_UNSUPPORTED;
665 }
666
667 Instance = MTFTP6_INSTANCE_FROM_THIS (Mtftp6);
668 Service = MTFTP6_SERVICE_FROM_THIS (This);
669
670 if (Instance->Service != Service) {
671 return EFI_INVALID_PARAMETER;
672 }
673
674 //
675 // Check whether the instance already in Destroy state.
676 //
677 if (Instance->InDestroy) {
678 return EFI_SUCCESS;
679 }
680
681 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
682
683 Instance->InDestroy = TRUE;
684
685 gBS->CloseProtocol (
686 Service->DummyUdpIo->UdpHandle,
687 &gEfiUdp6ProtocolGuid,
688 gMtftp6DriverBinding.DriverBindingHandle,
689 ChildHandle
690 );
691
692 if (Instance->UdpIo != NULL) {
693 gBS->CloseProtocol (
694 Instance->UdpIo->UdpHandle,
695 &gEfiUdp6ProtocolGuid,
696 gMtftp6DriverBinding.DriverBindingHandle,
697 Instance->Handle
698 );
699 }
700
701 if (Instance->McastUdpIo != NULL) {
702 gBS->CloseProtocol (
703 Instance->McastUdpIo->UdpHandle,
704 &gEfiUdp6ProtocolGuid,
705 gMtftp6DriverBinding.DriverBindingHandle,
706 Instance->Handle
707 );
708 }
709
710 //
711 // Uninstall the MTFTP6 protocol first to enable a top down destruction.
712 //
713 gBS->RestoreTPL (OldTpl);
714 Status = gBS->UninstallProtocolInterface (
715 ChildHandle,
716 &gEfiMtftp6ProtocolGuid,
717 Mtftp6
718 );
719 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
720 if (EFI_ERROR (Status)) {
721 Instance->InDestroy = FALSE;
722 gBS->RestoreTPL (OldTpl);
723 return Status;
724 }
725
726 //
727 // Remove the Mtftp6 instance from the children list of Mtftp6 service.
728 //
729 RemoveEntryList (&Instance->Link);
730 Service->ChildrenNum--;
731
732 gBS->RestoreTPL (OldTpl);
733
734 Mtftp6DestroyInstance (Instance);
735
736 return EFI_SUCCESS;
737}
UINT64 UINTN
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
EFI_STATUS EFIAPI Mtftp6DriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer)
Definition: Mtftp6Driver.c:447
VOID Mtftp6DestroyService(IN MTFTP6_SERVICE *Service)
Definition: Mtftp6Driver.c:36
EFI_STATUS EFIAPI Mtftp6ServiceBindingDestroyChild(IN EFI_SERVICE_BINDING_PROTOCOL *This, IN EFI_HANDLE ChildHandle)
Definition: Mtftp6Driver.c:636
EFI_STATUS EFIAPI Mtftp6DriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath)
Definition: Mtftp6Driver.c:351
VOID Mtftp6DestroyInstance(IN MTFTP6_INSTANCE *Instance)
Definition: Mtftp6Driver.c:147
EFI_STATUS EFIAPI Mtftp6DriverEntryPoint(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: Mtftp6Driver.c:281
EFI_STATUS EFIAPI Mtftp6DestroyChildEntryInHandleBuffer(IN LIST_ENTRY *Entry, IN VOID *Context)
Definition: Mtftp6Driver.c:239
EFI_STATUS Mtftp6CreateInstance(IN MTFTP6_SERVICE *Service, OUT MTFTP6_INSTANCE **Instance)
Definition: Mtftp6Driver.c:195
EFI_STATUS EFIAPI Mtftp6DriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath)
Definition: Mtftp6Driver.c:315
EFI_STATUS EFIAPI Mtftp6ServiceBindingCreateChild(IN EFI_SERVICE_BINDING_PROTOCOL *This, IN OUT EFI_HANDLE *ChildHandle)
Definition: Mtftp6Driver.c:537
EFI_STATUS Mtftp6CreateService(IN EFI_HANDLE Controller, IN EFI_HANDLE Image, OUT MTFTP6_SERVICE **Service)
Definition: Mtftp6Driver.c:71
EFI_STATUS EFIAPI Mtftp6ConfigDummyUdpIo(IN UDP_IO *UdpIo, IN VOID *Context)
VOID EFIAPI Mtftp6OnTimerTick(IN EFI_EVENT Event, IN VOID *Context)
VOID EFIAPI NetbufFree(IN NET_BUF *Nbuf)
Definition: NetBuffer.c:195
BOOLEAN EFIAPI NetIsInHandleBuffer(IN EFI_HANDLE Handle, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer OPTIONAL)
Definition: DxeNetLib.c:1306
EFI_HANDLE EFIAPI NetLibGetNicHandle(IN EFI_HANDLE Controller, IN EFI_GUID *ProtocolGuid)
Definition: DxeNetLib.c:3019
EFI_STATUS EFIAPI NetDestroyLinkList(IN LIST_ENTRY *List, IN NET_DESTROY_LINK_LIST_CALLBACK CallBack, IN VOID *Context OPTIONAL, OUT UINTN *ListLength OPTIONAL)
Definition: DxeNetLib.c:1236
EFI_STATUS EFIAPI UdpIoFreeIo(IN UDP_IO *UdpIo)
Definition: DxeUdpIoLib.c:809
UDP_IO *EFIAPI UdpIoCreateIo(IN EFI_HANDLE Controller, IN EFI_HANDLE ImageHandle, IN UDP_IO_CONFIG Configure, IN UINT8 UdpVersion, IN VOID *Context)
Definition: DxeUdpIoLib.c:602
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
UINTN EFI_TPL
Definition: UefiBaseType.h:41
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_STATUS EFIAPI EfiLibInstallDriverBindingComponentName2(IN CONST EFI_HANDLE ImageHandle, IN CONST EFI_SYSTEM_TABLE *SystemTable, IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, IN EFI_HANDLE DriverBindingHandle, IN CONST EFI_COMPONENT_NAME_PROTOCOL *ComponentName OPTIONAL, IN CONST EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2 OPTIONAL)
@ TimerPeriodic
Definition: UefiSpec.h:535