TianoCore EDK2 master
Loading...
Searching...
No Matches
Mtftp6Support.c
Go to the documentation of this file.
1
10#include "Mtftp6Impl.h"
11
23 IN UINT16 Start,
24 IN UINT16 End
25 )
26{
27 MTFTP6_BLOCK_RANGE *Range;
28
29 Range = AllocateZeroPool (sizeof (MTFTP6_BLOCK_RANGE));
30
31 if (Range == NULL) {
32 return NULL;
33 }
34
35 InitializeListHead (&Range->Link);
36 Range->Start = Start;
37 Range->End = End;
38 Range->Bound = End;
39
40 return Range;
41}
42
65 IN LIST_ENTRY *Head,
66 IN UINT16 Start,
67 IN UINT16 End
68 )
69{
70 MTFTP6_BLOCK_RANGE *Range;
71
72 Range = Mtftp6AllocateRange (Start, End);
73
74 if (Range == NULL) {
75 return EFI_OUT_OF_RESOURCES;
76 }
77
78 InsertTailList (Head, &Range->Link);
79 return EFI_SUCCESS;
80}
81
91INTN
93 IN LIST_ENTRY *Head
94 )
95{
96 MTFTP6_BLOCK_RANGE *Range;
97
98 if (IsListEmpty (Head)) {
99 return -1;
100 }
101
102 Range = NET_LIST_HEAD (Head, MTFTP6_BLOCK_RANGE, Link);
103 return Range->Start;
104}
105
117VOID
119 IN LIST_ENTRY *Head,
120 IN UINT16 Last
121 )
122{
123 MTFTP6_BLOCK_RANGE *Range;
124
125 //
126 // Iterate from the tail to head to remove the block number
127 // after the last.
128 //
129 while (!IsListEmpty (Head)) {
130 Range = NET_LIST_TAIL (Head, MTFTP6_BLOCK_RANGE, Link);
131
132 if (Range->Start > Last) {
133 RemoveEntryList (&Range->Link);
134 FreePool (Range);
135 continue;
136 }
137
138 if (Range->End > Last) {
139 Range->End = Last;
140 }
141
142 return;
143 }
144}
145
161 IN LIST_ENTRY *Head,
162 IN UINT16 Num,
163 IN BOOLEAN Completed,
164 OUT UINT64 *BlockCounter
165 )
166{
167 MTFTP6_BLOCK_RANGE *Range;
168 MTFTP6_BLOCK_RANGE *NewRange;
169 LIST_ENTRY *Entry;
170
171 NET_LIST_FOR_EACH (Entry, Head) {
172 //
173 // Each block represents a hole [Start, End] in the file,
174 // skip to the first range with End >= Num
175 //
176 Range = NET_LIST_USER_STRUCT (Entry, MTFTP6_BLOCK_RANGE, Link);
177
178 if (Range->End < Num) {
179 continue;
180 }
181
182 //
183 // There are three different cases for Start
184 // 1. (Start > Num) && (End >= Num):
185 // because all the holes before this one has the condition of
186 // End < Num, so this block number has been removed.
187 //
188 // 2. (Start == Num) && (End >= Num):
189 // Need to increase the Start by one, and if End == Num, this
190 // hole has been removed completely, remove it.
191 //
192 // 3. (Start < Num) && (End >= Num):
193 // if End == Num, only need to decrease the End by one because
194 // we have (Start < Num) && (Num == End), so (Start <= End - 1).
195 // if (End > Num), the hold is split into two holes, with
196 // [Start, Num - 1] and [Num + 1, End].
197 //
198 if (Range->Start > Num) {
199 return EFI_NOT_FOUND;
200 } else if (Range->Start == Num) {
201 Range->Start++;
202
203 //
204 // Note that: RFC 1350 does not mention block counter roll-over,
205 // but several TFTP hosts implement the roll-over be able to accept
206 // transfers of unlimited size. There is no consensus, however, whether
207 // the counter should wrap around to zero or to one. Many implementations
208 // wrap to zero, because this is the simplest to implement. Here we choose
209 // this solution.
210 //
211 *BlockCounter = Num;
212
213 if (Range->Round > 0) {
214 *BlockCounter += Range->Bound + MultU64x32 (Range->Round - 1, (UINT32)(Range->Bound + 1)) + 1;
215 }
216
217 if (Range->Start > Range->Bound) {
218 Range->Start = 0;
219 Range->Round++;
220 }
221
222 if ((Range->Start > Range->End) || Completed) {
223 RemoveEntryList (&Range->Link);
224 FreePool (Range);
225 }
226
227 return EFI_SUCCESS;
228 } else {
229 if (Range->End == Num) {
230 Range->End--;
231 } else {
232 NewRange = Mtftp6AllocateRange ((UINT16)(Num + 1), (UINT16)Range->End);
233
234 if (NewRange == NULL) {
235 return EFI_OUT_OF_RESOURCES;
236 }
237
238 Range->End = Num - 1;
239 NetListInsertAfter (&Range->Link, &NewRange->Link);
240 }
241
242 return EFI_SUCCESS;
243 }
244 }
245
246 return EFI_NOT_FOUND;
247}
248
263 IN UDP_IO *UdpIo,
264 IN EFI_UDP6_CONFIG_DATA *UdpCfgData
265 )
266{
267 EFI_IP6_MODE_DATA Ip6Mode;
268 EFI_UDP6_PROTOCOL *Udp6;
269 EFI_STATUS Status;
270 EFI_EVENT Event;
271
272 Event = NULL;
273 Udp6 = UdpIo->Protocol.Udp6;
274
275 //
276 // Create a timer to check whether the Ip6 instance configured or not.
277 //
278 Status = gBS->CreateEvent (
279 EVT_TIMER,
280 TPL_CALLBACK,
281 NULL,
282 NULL,
283 &Event
284 );
285 if (EFI_ERROR (Status)) {
286 goto ON_EXIT;
287 }
288
289 Status = gBS->SetTimer (
290 Event,
292 MTFTP6_GET_MAPPING_TIMEOUT * MTFTP6_TICK_PER_SECOND
293 );
294 if (EFI_ERROR (Status)) {
295 goto ON_EXIT;
296 }
297
298 //
299 // Check the Ip6 mode data till timeout.
300 //
301 while (EFI_ERROR (gBS->CheckEvent (Event))) {
302 Udp6->Poll (Udp6);
303
304 Status = Udp6->GetModeData (Udp6, NULL, &Ip6Mode, NULL, NULL);
305
306 if (!EFI_ERROR (Status)) {
307 if (Ip6Mode.AddressList != NULL) {
308 FreePool (Ip6Mode.AddressList);
309 }
310
311 if (Ip6Mode.GroupTable != NULL) {
312 FreePool (Ip6Mode.GroupTable);
313 }
314
315 if (Ip6Mode.RouteTable != NULL) {
316 FreePool (Ip6Mode.RouteTable);
317 }
318
319 if (Ip6Mode.NeighborCache != NULL) {
320 FreePool (Ip6Mode.NeighborCache);
321 }
322
323 if (Ip6Mode.PrefixTable != NULL) {
324 FreePool (Ip6Mode.PrefixTable);
325 }
326
327 if (Ip6Mode.IcmpTypeList != NULL) {
328 FreePool (Ip6Mode.IcmpTypeList);
329 }
330
331 if (Ip6Mode.IsConfigured) {
332 //
333 // Continue to configure the Udp6 instance.
334 //
335 Status = Udp6->Configure (Udp6, UdpCfgData);
336 } else {
337 Status = EFI_NO_MAPPING;
338 }
339 }
340 }
341
342ON_EXIT:
343
344 if (Event != NULL) {
345 gBS->CloseEvent (Event);
346 }
347
348 return Status;
349}
350
361EFIAPI
363 IN UDP_IO *UdpIo,
364 IN VOID *Context
365 )
366{
367 return EFI_SUCCESS;
368}
369
386 IN UDP_IO *UdpIo,
387 IN EFI_IPv6_ADDRESS *ServerIp,
388 IN UINT16 ServerPort,
389 IN EFI_IPv6_ADDRESS *LocalIp,
390 IN UINT16 LocalPort
391 )
392{
393 EFI_STATUS Status;
394 EFI_UDP6_PROTOCOL *Udp6;
395 EFI_UDP6_CONFIG_DATA *Udp6Cfg;
396
397 Udp6 = UdpIo->Protocol.Udp6;
398 Udp6Cfg = &(UdpIo->Config.Udp6);
399
400 ZeroMem (Udp6Cfg, sizeof (EFI_UDP6_CONFIG_DATA));
401
402 //
403 // Set the Udp6 Io configure data.
404 //
405 Udp6Cfg->AcceptPromiscuous = FALSE;
406 Udp6Cfg->AcceptAnyPort = FALSE;
407 Udp6Cfg->AllowDuplicatePort = FALSE;
408 Udp6Cfg->TrafficClass = 0;
409 Udp6Cfg->HopLimit = 128;
410 Udp6Cfg->ReceiveTimeout = 0;
411 Udp6Cfg->TransmitTimeout = 0;
412 Udp6Cfg->StationPort = LocalPort;
413 Udp6Cfg->RemotePort = ServerPort;
414
415 CopyMem (
416 &Udp6Cfg->StationAddress,
417 LocalIp,
418 sizeof (EFI_IPv6_ADDRESS)
419 );
420
421 CopyMem (
422 &Udp6Cfg->RemoteAddress,
423 ServerIp,
424 sizeof (EFI_IPv6_ADDRESS)
425 );
426
427 //
428 // Configure the Udp6 instance with current configure data.
429 //
430 Status = Udp6->Configure (Udp6, Udp6Cfg);
431
432 if (Status == EFI_NO_MAPPING) {
433 return Mtftp6GetMapping (UdpIo, Udp6Cfg);
434 }
435
436 return Status;
437}
438
452 IN MTFTP6_INSTANCE *Instance,
453 IN UINT16 Operation
454 )
455{
456 EFI_MTFTP6_PACKET *Packet;
457 EFI_MTFTP6_OPTION *Options;
458 EFI_MTFTP6_TOKEN *Token;
459 RETURN_STATUS Status;
460 NET_BUF *Nbuf;
461 UINT8 *Mode;
462 UINT8 *Cur;
463 UINTN Index;
464 UINT32 BufferLength;
465 UINTN FileNameLength;
466 UINTN ModeLength;
467 UINTN OptionStrLength;
468 UINTN ValueStrLength;
469
470 Token = Instance->Token;
471 Options = Token->OptionList;
472 Mode = Token->ModeStr;
473
474 if (Mode == NULL) {
475 Mode = (UINT8 *)"octet";
476 }
477
478 //
479 // The header format of RRQ/WRQ packet is:
480 //
481 // 2 bytes string 1 byte string 1 byte
482 // ------------------------------------------------
483 // | Opcode | Filename | 0 | Mode | 0 |
484 // ------------------------------------------------
485 //
486 // The common option format is:
487 //
488 // string 1 byte string 1 byte
489 // ---------------------------------------
490 // | OptionStr | 0 | ValueStr | 0 |
491 // ---------------------------------------
492 //
493
494 //
495 // Compute the size of new Mtftp6 packet.
496 //
497 FileNameLength = AsciiStrLen ((CHAR8 *)Token->Filename);
498 ModeLength = AsciiStrLen ((CHAR8 *)Mode);
499 BufferLength = (UINT32)FileNameLength + (UINT32)ModeLength + 4;
500
501 for (Index = 0; Index < Token->OptionCount; Index++) {
502 OptionStrLength = AsciiStrLen ((CHAR8 *)Options[Index].OptionStr);
503 ValueStrLength = AsciiStrLen ((CHAR8 *)Options[Index].ValueStr);
504 BufferLength += (UINT32)OptionStrLength + (UINT32)ValueStrLength + 2;
505 }
506
507 //
508 // Allocate a packet then copy the data.
509 //
510 if ((Nbuf = NetbufAlloc (BufferLength)) == NULL) {
511 return EFI_OUT_OF_RESOURCES;
512 }
513
514 //
515 // Copy the opcode, filename and mode into packet.
516 //
517 Packet = (EFI_MTFTP6_PACKET *)NetbufAllocSpace (Nbuf, BufferLength, FALSE);
518 ASSERT (Packet != NULL);
519
520 Packet->OpCode = HTONS (Operation);
521 BufferLength -= sizeof (Packet->OpCode);
522
523 Cur = Packet->Rrq.Filename;
524 Status = AsciiStrCpyS ((CHAR8 *)Cur, BufferLength, (CHAR8 *)Token->Filename);
525 ASSERT_EFI_ERROR (Status);
526 BufferLength -= (UINT32)(FileNameLength + 1);
527 Cur += FileNameLength + 1;
528 Status = AsciiStrCpyS ((CHAR8 *)Cur, BufferLength, (CHAR8 *)Mode);
529 ASSERT_EFI_ERROR (Status);
530 BufferLength -= (UINT32)(ModeLength + 1);
531 Cur += ModeLength + 1;
532
533 //
534 // Copy all the extension options into the packet.
535 //
536 for (Index = 0; Index < Token->OptionCount; ++Index) {
537 OptionStrLength = AsciiStrLen ((CHAR8 *)Options[Index].OptionStr);
538 ValueStrLength = AsciiStrLen ((CHAR8 *)Options[Index].ValueStr);
539
540 Status = AsciiStrCpyS ((CHAR8 *)Cur, BufferLength, (CHAR8 *)Options[Index].OptionStr);
541 ASSERT_EFI_ERROR (Status);
542 BufferLength -= (UINT32)(OptionStrLength + 1);
543 Cur += OptionStrLength + 1;
544
545 Status = AsciiStrCpyS ((CHAR8 *)Cur, BufferLength, (CHAR8 *)Options[Index].ValueStr);
546 ASSERT_EFI_ERROR (Status);
547 BufferLength -= (UINT32)(ValueStrLength + 1);
548 Cur += ValueStrLength + 1;
549 }
550
551 //
552 // Save the packet buf for retransmit
553 //
554 if (Instance->LastPacket != NULL) {
555 NetbufFree (Instance->LastPacket);
556 }
557
558 Instance->LastPacket = Nbuf;
559 Instance->CurRetry = 0;
560
561 return Mtftp6TransmitPacket (Instance, Nbuf);
562}
563
578 IN MTFTP6_INSTANCE *Instance,
579 IN UINT16 ErrCode,
580 IN UINT8 *ErrInfo
581 )
582{
583 NET_BUF *Nbuf;
584 EFI_MTFTP6_PACKET *TftpError;
585 UINT32 Len;
586
587 //
588 // Allocate a packet then copy the data.
589 //
590 Len = (UINT32)(AsciiStrLen ((CHAR8 *)ErrInfo) + sizeof (EFI_MTFTP6_ERROR_HEADER));
591 Nbuf = NetbufAlloc (Len);
592
593 if (Nbuf == NULL) {
594 return EFI_OUT_OF_RESOURCES;
595 }
596
597 TftpError = (EFI_MTFTP6_PACKET *)NetbufAllocSpace (Nbuf, Len, FALSE);
598
599 if (TftpError == NULL) {
600 NetbufFree (Nbuf);
601 return EFI_OUT_OF_RESOURCES;
602 }
603
604 TftpError->OpCode = HTONS (EFI_MTFTP6_OPCODE_ERROR);
605 TftpError->Error.ErrorCode = HTONS (ErrCode);
606
607 AsciiStrCpyS ((CHAR8 *)TftpError->Error.ErrorMessage, AsciiStrLen ((CHAR8 *)ErrInfo) + 1, (CHAR8 *)ErrInfo);
608
609 //
610 // Save the packet buf for retransmit
611 //
612 if (Instance->LastPacket != NULL) {
613 NetbufFree (Instance->LastPacket);
614 }
615
616 Instance->LastPacket = Nbuf;
617 Instance->CurRetry = 0;
618
619 return Mtftp6TransmitPacket (Instance, Nbuf);
620}
621
631VOID
632EFIAPI
634 IN NET_BUF *Packet,
635 IN UDP_END_POINT *UdpEpt,
636 IN EFI_STATUS IoStatus,
637 IN VOID *Context
638 )
639{
640 NetbufFree (Packet);
641 *(BOOLEAN *)Context = TRUE;
642}
643
656 IN MTFTP6_INSTANCE *Instance,
657 IN NET_BUF *Packet
658 )
659{
660 EFI_UDP6_PROTOCOL *Udp6;
661 EFI_UDP6_CONFIG_DATA Udp6CfgData;
662 EFI_STATUS Status;
663 UINT16 *Temp;
664 UINT16 Value;
665 UINT16 OpCode;
666
667 ZeroMem (&Udp6CfgData, sizeof (EFI_UDP6_CONFIG_DATA));
668 Udp6 = Instance->UdpIo->Protocol.Udp6;
669
670 //
671 // Set the live time of the packet.
672 //
673 Instance->PacketToLive = Instance->IsMaster ? Instance->Timeout : (Instance->Timeout * 2);
674
675 Temp = (UINT16 *)NetbufGetByte (Packet, 0, NULL);
676 ASSERT (Temp != NULL);
677
678 Value = *Temp;
679 OpCode = NTOHS (Value);
680
681 if ((OpCode == EFI_MTFTP6_OPCODE_RRQ) || (OpCode == EFI_MTFTP6_OPCODE_DIR) || (OpCode == EFI_MTFTP6_OPCODE_WRQ)) {
682 //
683 // For the Rrq, Dir, Wrq requests of the operation, configure the Udp6Io as
684 // (serverip, 69, localip, localport) to send.
685 // Usually local address and local port are both default as zero.
686 //
687 Status = Udp6->Configure (Udp6, NULL);
688
689 if (EFI_ERROR (Status)) {
690 return Status;
691 }
692
693 Status = Mtftp6ConfigUdpIo (
694 Instance->UdpIo,
695 &Instance->ServerIp,
696 Instance->ServerCmdPort,
697 &Instance->Config->StationIp,
698 Instance->Config->LocalPort
699 );
700
701 if (EFI_ERROR (Status)) {
702 return Status;
703 }
704
705 //
706 // Get the current local address and port by get Udp6 mode data.
707 //
708 Status = Udp6->GetModeData (Udp6, &Udp6CfgData, NULL, NULL, NULL);
709 if (EFI_ERROR (Status)) {
710 return Status;
711 }
712
713 NET_GET_REF (Packet);
714
715 Instance->IsTransmitted = FALSE;
716
717 Status = UdpIoSendDatagram (
718 Instance->UdpIo,
719 Packet,
720 NULL,
721 NULL,
723 &Instance->IsTransmitted
724 );
725
726 if (EFI_ERROR (Status)) {
727 NET_PUT_REF (Packet);
728 return Status;
729 }
730
731 //
732 // Poll till the packet sent out from the ip6 queue.
733 //
734 gBS->RestoreTPL (Instance->OldTpl);
735
736 while (!Instance->IsTransmitted) {
737 Udp6->Poll (Udp6);
738 }
739
740 Instance->OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
741
742 //
743 // For the subsequent exchange of such requests, reconfigure the Udp6Io as
744 // (serverip, 0, localip, localport) to receive.
745 // Currently local address and local port are specified by Udp6 mode data.
746 //
747 Status = Udp6->Configure (Udp6, NULL);
748
749 if (EFI_ERROR (Status)) {
750 return Status;
751 }
752
753 Status = Mtftp6ConfigUdpIo (
754 Instance->UdpIo,
755 &Instance->ServerIp,
756 Instance->ServerDataPort,
757 &Udp6CfgData.StationAddress,
758 Udp6CfgData.StationPort
759 );
760 } else {
761 //
762 // For the data exchange, configure the Udp6Io as (serverip, dataport,
763 // localip, localport) to send/receive.
764 // Currently local address and local port are specified by Udp6 mode data.
765 //
766 Status = Udp6->GetModeData (Udp6, &Udp6CfgData, NULL, NULL, NULL);
767 if (EFI_ERROR (Status)) {
768 return Status;
769 }
770
771 if (Udp6CfgData.RemotePort != Instance->ServerDataPort) {
772 Status = Udp6->Configure (Udp6, NULL);
773
774 if (EFI_ERROR (Status)) {
775 return Status;
776 }
777
778 Status = Mtftp6ConfigUdpIo (
779 Instance->UdpIo,
780 &Instance->ServerIp,
781 Instance->ServerDataPort,
782 &Udp6CfgData.StationAddress,
783 Udp6CfgData.StationPort
784 );
785
786 if (EFI_ERROR (Status)) {
787 return Status;
788 }
789 }
790
791 NET_GET_REF (Packet);
792
793 Instance->IsTransmitted = FALSE;
794
795 Status = UdpIoSendDatagram (
796 Instance->UdpIo,
797 Packet,
798 NULL,
799 NULL,
801 &Instance->IsTransmitted
802 );
803
804 if (EFI_ERROR (Status)) {
805 NET_PUT_REF (Packet);
806 }
807
808 //
809 // Poll till the packet sent out from the ip6 queue.
810 //
811 gBS->RestoreTPL (Instance->OldTpl);
812
813 while (!Instance->IsTransmitted) {
814 Udp6->Poll (Udp6);
815 }
816
817 Instance->OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
818 }
819
820 return Status;
821}
822
838EFIAPI
841 IN EFI_MTFTP6_TOKEN *Token,
842 IN UINT16 PacketLen,
843 IN EFI_MTFTP6_PACKET *Packet
844 )
845{
846 MTFTP6_GETINFO_CONTEXT *Context;
847 UINT16 OpCode;
848
849 Context = (MTFTP6_GETINFO_CONTEXT *)Token->Context;
850 OpCode = NTOHS (Packet->OpCode);
851
852 //
853 // Set the GetInfo's return status according to the OpCode.
854 //
855 switch (OpCode) {
857 Context->Status = EFI_TFTP_ERROR;
858 break;
859
861 Context->Status = EFI_SUCCESS;
862 break;
863
864 default:
865 Context->Status = EFI_PROTOCOL_ERROR;
866 }
867
868 //
869 // Allocate buffer then copy the packet over. Use gBS->AllocatePool
870 // in case NetAllocatePool will implements something tricky.
871 //
872 *(Context->Packet) = AllocateZeroPool (PacketLen);
873
874 if (*(Context->Packet) == NULL) {
875 Context->Status = EFI_OUT_OF_RESOURCES;
876 return EFI_ABORTED;
877 }
878
879 *(Context->PacketLen) = PacketLen;
880 CopyMem (*(Context->Packet), Packet, PacketLen);
881
882 return EFI_ABORTED;
883}
884
892VOID
894 IN MTFTP6_INSTANCE *Instance,
895 IN EFI_STATUS Result
896 )
897{
898 LIST_ENTRY *Entry;
899 LIST_ENTRY *Next;
900 MTFTP6_BLOCK_RANGE *Block;
901
902 //
903 // Clean up the current token and event.
904 //
905 if (Instance->Token != NULL) {
906 Instance->Token->Status = Result;
907 if (Instance->Token->Event != NULL) {
908 gBS->SignalEvent (Instance->Token->Event);
909 }
910
911 Instance->Token = NULL;
912 }
913
914 //
915 // Clean up the corresponding Udp6Io.
916 //
917 if (Instance->UdpIo != NULL) {
918 UdpIoCleanIo (Instance->UdpIo);
919 }
920
921 if (Instance->McastUdpIo != NULL) {
922 gBS->CloseProtocol (
923 Instance->McastUdpIo->UdpHandle,
924 &gEfiUdp6ProtocolGuid,
925 Instance->McastUdpIo->Image,
926 Instance->Handle
927 );
928 UdpIoFreeIo (Instance->McastUdpIo);
929 Instance->McastUdpIo = NULL;
930 }
931
932 //
933 // Clean up the stored last packet.
934 //
935 if (Instance->LastPacket != NULL) {
936 NetbufFree (Instance->LastPacket);
937 Instance->LastPacket = NULL;
938 }
939
940 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Instance->BlkList) {
941 Block = NET_LIST_USER_STRUCT (Entry, MTFTP6_BLOCK_RANGE, Link);
942 RemoveEntryList (Entry);
943 FreePool (Block);
944 }
945
946 //
947 // Reinitialize the corresponding fields of the Mtftp6 operation.
948 //
949 ZeroMem (&Instance->ExtInfo, sizeof (MTFTP6_EXT_OPTION_INFO));
950 ZeroMem (&Instance->ServerIp, sizeof (EFI_IPv6_ADDRESS));
951 ZeroMem (&Instance->McastIp, sizeof (EFI_IPv6_ADDRESS));
952
953 Instance->ServerCmdPort = 0;
954 Instance->ServerDataPort = 0;
955 Instance->McastPort = 0;
956 Instance->BlkSize = 0;
957 Instance->Operation = 0;
958 Instance->WindowSize = 1;
959 Instance->TotalBlock = 0;
960 Instance->AckedBlock = 0;
961 Instance->LastBlk = 0;
962 Instance->PacketToLive = 0;
963 Instance->MaxRetry = 0;
964 Instance->CurRetry = 0;
965 Instance->Timeout = 0;
966 Instance->IsMaster = TRUE;
967}
968
986 IN EFI_MTFTP6_TOKEN *Token,
987 IN UINT16 OpCode
988 )
989{
990 MTFTP6_INSTANCE *Instance;
991 EFI_STATUS Status;
992
993 if ((This == NULL) ||
994 (Token == NULL) ||
995 (Token->Filename == NULL) ||
996 ((Token->OptionCount != 0) && (Token->OptionList == NULL)) ||
997 ((Token->OverrideData != NULL) && !NetIp6IsValidUnicast (&Token->OverrideData->ServerIp))
998 )
999 {
1000 return EFI_INVALID_PARAMETER;
1001 }
1002
1003 //
1004 // At least define one method to collect the data for download.
1005 //
1006 if (((OpCode == EFI_MTFTP6_OPCODE_RRQ) || (OpCode == EFI_MTFTP6_OPCODE_DIR)) &&
1007 (Token->Buffer == NULL) &&
1008 (Token->CheckPacket == NULL)
1009 )
1010 {
1011 return EFI_INVALID_PARAMETER;
1012 }
1013
1014 //
1015 // At least define one method to provide the data for upload.
1016 //
1017 if ((OpCode == EFI_MTFTP6_OPCODE_WRQ) && (Token->Buffer == NULL) && (Token->PacketNeeded == NULL)) {
1018 return EFI_INVALID_PARAMETER;
1019 }
1020
1021 Instance = MTFTP6_INSTANCE_FROM_THIS (This);
1022
1023 if (Instance->Config == NULL) {
1024 return EFI_NOT_STARTED;
1025 }
1026
1027 if (Instance->Token != NULL) {
1028 return EFI_ACCESS_DENIED;
1029 }
1030
1031 Status = EFI_SUCCESS;
1032 Instance->OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1033
1034 Instance->Operation = OpCode;
1035
1036 //
1037 // Parse the extension options in the request packet.
1038 //
1039 if (Token->OptionCount != 0) {
1041 Token->OptionList,
1042 Token->OptionCount,
1043 TRUE,
1044 Instance->Operation,
1045 &Instance->ExtInfo
1046 );
1047
1048 if (EFI_ERROR (Status)) {
1049 goto ON_ERROR;
1050 }
1051 }
1052
1053 //
1054 // Initialize runtime data from config data or override data.
1055 //
1056 Instance->Token = Token;
1057 Instance->ServerCmdPort = Instance->Config->InitialServerPort;
1058 Instance->ServerDataPort = 0;
1059 Instance->MaxRetry = Instance->Config->TryCount;
1060 Instance->Timeout = Instance->Config->TimeoutValue;
1061 Instance->IsMaster = TRUE;
1062
1063 CopyMem (
1064 &Instance->ServerIp,
1065 &Instance->Config->ServerIp,
1066 sizeof (EFI_IPv6_ADDRESS)
1067 );
1068
1069 if (Token->OverrideData != NULL) {
1070 Instance->ServerCmdPort = Token->OverrideData->ServerPort;
1071 Instance->MaxRetry = Token->OverrideData->TryCount;
1072 Instance->Timeout = Token->OverrideData->TimeoutValue;
1073
1074 CopyMem (
1075 &Instance->ServerIp,
1076 &Token->OverrideData->ServerIp,
1077 sizeof (EFI_IPv6_ADDRESS)
1078 );
1079 }
1080
1081 //
1082 // Set default value for undefined parameters.
1083 //
1084 if (Instance->ServerCmdPort == 0) {
1085 Instance->ServerCmdPort = MTFTP6_DEFAULT_SERVER_CMD_PORT;
1086 }
1087
1088 if (Instance->BlkSize == 0) {
1089 Instance->BlkSize = MTFTP6_DEFAULT_BLK_SIZE;
1090 }
1091
1092 if (Instance->WindowSize == 0) {
1093 Instance->WindowSize = MTFTP6_DEFAULT_WINDOWSIZE;
1094 }
1095
1096 if (Instance->MaxRetry == 0) {
1097 Instance->MaxRetry = MTFTP6_DEFAULT_MAX_RETRY;
1098 }
1099
1100 if (Instance->Timeout == 0) {
1101 Instance->Timeout = MTFTP6_DEFAULT_TIMEOUT;
1102 }
1103
1104 Token->Status = EFI_NOT_READY;
1105
1106 //
1107 // Switch the routines by the operation code.
1108 //
1109 switch (OpCode) {
1111 Status = Mtftp6RrqStart (Instance, OpCode);
1112 break;
1113
1115 Status = Mtftp6RrqStart (Instance, OpCode);
1116 break;
1117
1119 Status = Mtftp6WrqStart (Instance, OpCode);
1120 break;
1121
1122 default:
1123 Status = EFI_DEVICE_ERROR;
1124 goto ON_ERROR;
1125 }
1126
1127 if (EFI_ERROR (Status)) {
1128 goto ON_ERROR;
1129 }
1130
1131 //
1132 // Return immediately for asynchronous or poll the instance for synchronous.
1133 //
1134 gBS->RestoreTPL (Instance->OldTpl);
1135
1136 if (Token->Event == NULL) {
1137 while (Token->Status == EFI_NOT_READY) {
1138 This->Poll (This);
1139 }
1140
1141 return Token->Status;
1142 }
1143
1144 return EFI_SUCCESS;
1145
1146ON_ERROR:
1147
1148 Mtftp6OperationClean (Instance, Status);
1149 gBS->RestoreTPL (Instance->OldTpl);
1150
1151 return Status;
1152}
1153
1161VOID
1162EFIAPI
1164 IN EFI_EVENT Event,
1165 IN VOID *Context
1166 )
1167{
1168 MTFTP6_SERVICE *Service;
1169 MTFTP6_INSTANCE *Instance;
1170 LIST_ENTRY *Entry;
1171 LIST_ENTRY *Next;
1172 EFI_MTFTP6_TOKEN *Token;
1173 EFI_STATUS Status;
1174
1175 Service = (MTFTP6_SERVICE *)Context;
1176
1177 //
1178 // Iterate through all the children of the Mtftp service instance. Time
1179 // out the packet. If maximum retries reached, clean the session up.
1180 //
1181 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Service->Children) {
1182 Instance = NET_LIST_USER_STRUCT (Entry, MTFTP6_INSTANCE, Link);
1183
1184 if (Instance->Token == NULL) {
1185 continue;
1186 }
1187
1188 if (Instance->PacketToLive > 0) {
1189 Instance->PacketToLive--;
1190 continue;
1191 }
1192
1193 Instance->CurRetry++;
1194 Token = Instance->Token;
1195
1196 if (Token->TimeoutCallback != NULL) {
1197 //
1198 // Call the timeout callback routine if has.
1199 //
1200 Status = Token->TimeoutCallback (&Instance->Mtftp6, Token);
1201
1202 if (EFI_ERROR (Status)) {
1204 Instance,
1206 (UINT8 *)"User aborted the transfer in time out"
1207 );
1208 Mtftp6OperationClean (Instance, EFI_ABORTED);
1209 continue;
1210 }
1211 }
1212
1213 //
1214 // Retransmit the packet if haven't reach the maximum retry count,
1215 // otherwise exit the transfer.
1216 //
1217 if (Instance->CurRetry < Instance->MaxRetry) {
1218 Mtftp6TransmitPacket (Instance, Instance->LastPacket);
1219 } else {
1220 Mtftp6OperationClean (Instance, EFI_TIMEOUT);
1221 continue;
1222 }
1223 }
1224}
UINT64 UINTN
INT64 INTN
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
UINTN EFIAPI AsciiStrLen(IN CONST CHAR8 *String)
Definition: String.c:641
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
UINT64 EFIAPI MultU64x32(IN UINT64 Multiplicand, IN UINT32 Multiplier)
Definition: MultU64x32.c:27
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
RETURN_STATUS EFIAPI AsciiStrCpyS(OUT CHAR8 *Destination, IN UINTN DestMax, IN CONST CHAR8 *Source)
Definition: SafeString.c:1797
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 ZeroMem(OUT VOID *Buffer, 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
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define EFI_MTFTP6_OPCODE_ERROR
The MTFTPv6 packet is an error packet.
Definition: Mtftp6.h:39
#define EFI_MTFTP6_OPCODE_OACK
The MTFTPv6 packet is an option acknowledgement packet.
Definition: Mtftp6.h:40
#define EFI_MTFTP6_OPCODE_WRQ
The MTFTPv6 packet is a write request.
Definition: Mtftp6.h:36
#define EFI_MTFTP6_OPCODE_RRQ
The MTFTPv6 packet is a read request.
Definition: Mtftp6.h:35
#define EFI_MTFTP6_ERRORCODE_REQUEST_DENIED
Definition: Mtftp6.h:84
#define EFI_MTFTP6_OPCODE_DIR
The MTFTPv6 packet is a directory query packet.
Definition: Mtftp6.h:41
EFI_STATUS Mtftp6ParseExtensionOption(IN EFI_MTFTP6_OPTION *Options, IN UINT32 Count, IN BOOLEAN IsRequest, IN UINT16 Operation, IN MTFTP6_EXT_OPTION_INFO *ExtInfo)
Definition: Mtftp6Option.c:147
EFI_STATUS Mtftp6RrqStart(IN MTFTP6_INSTANCE *Instance, IN UINT16 Operation)
Definition: Mtftp6Rrq.c:905
EFI_STATUS Mtftp6RemoveBlockNum(IN LIST_ENTRY *Head, IN UINT16 Num, IN BOOLEAN Completed, OUT UINT64 *BlockCounter)
EFI_STATUS Mtftp6SendError(IN MTFTP6_INSTANCE *Instance, IN UINT16 ErrCode, IN UINT8 *ErrInfo)
EFI_STATUS EFIAPI Mtftp6CheckPacket(IN EFI_MTFTP6_PROTOCOL *This, IN EFI_MTFTP6_TOKEN *Token, IN UINT16 PacketLen, IN EFI_MTFTP6_PACKET *Packet)
EFI_STATUS Mtftp6GetMapping(IN UDP_IO *UdpIo, IN EFI_UDP6_CONFIG_DATA *UdpCfgData)
EFI_STATUS EFIAPI Mtftp6ConfigDummyUdpIo(IN UDP_IO *UdpIo, IN VOID *Context)
EFI_STATUS Mtftp6TransmitPacket(IN MTFTP6_INSTANCE *Instance, IN NET_BUF *Packet)
EFI_STATUS Mtftp6SendRequest(IN MTFTP6_INSTANCE *Instance, IN UINT16 Operation)
INTN Mtftp6GetNextBlockNum(IN LIST_ENTRY *Head)
Definition: Mtftp6Support.c:92
VOID EFIAPI Mtftp6OnPacketSent(IN NET_BUF *Packet, IN UDP_END_POINT *UdpEpt, IN EFI_STATUS IoStatus, IN VOID *Context)
EFI_STATUS Mtftp6InitBlockRange(IN LIST_ENTRY *Head, IN UINT16 Start, IN UINT16 End)
Definition: Mtftp6Support.c:64
MTFTP6_BLOCK_RANGE * Mtftp6AllocateRange(IN UINT16 Start, IN UINT16 End)
Definition: Mtftp6Support.c:22
EFI_STATUS Mtftp6OperationStart(IN EFI_MTFTP6_PROTOCOL *This, IN EFI_MTFTP6_TOKEN *Token, IN UINT16 OpCode)
VOID Mtftp6SetLastBlockNum(IN LIST_ENTRY *Head, IN UINT16 Last)
VOID EFIAPI Mtftp6OnTimerTick(IN EFI_EVENT Event, IN VOID *Context)
VOID Mtftp6OperationClean(IN MTFTP6_INSTANCE *Instance, IN EFI_STATUS Result)
EFI_STATUS Mtftp6ConfigUdpIo(IN UDP_IO *UdpIo, IN EFI_IPv6_ADDRESS *ServerIp, IN UINT16 ServerPort, IN EFI_IPv6_ADDRESS *LocalIp, IN UINT16 LocalPort)
EFI_STATUS Mtftp6WrqStart(IN MTFTP6_INSTANCE *Instance, IN UINT16 Operation)
Definition: Mtftp6Wrq.c:561
VOID EFIAPI NetbufFree(IN NET_BUF *Nbuf)
Definition: NetBuffer.c:195
BOOLEAN EFIAPI NetIp6IsValidUnicast(IN EFI_IPv6_ADDRESS *Ip6)
Definition: DxeNetLib.c:725
VOID EFIAPI NetListInsertAfter(IN OUT LIST_ENTRY *PrevEntry, IN OUT LIST_ENTRY *NewEntry)
Definition: DxeNetLib.c:1172
NET_BUF *EFIAPI NetbufAlloc(IN UINT32 Len)
Definition: NetBuffer.c:89
UINT8 *EFIAPI NetbufAllocSpace(IN OUT NET_BUF *Nbuf, IN UINT32 Len, IN BOOLEAN FromHead)
Definition: NetBuffer.c:1015
UINT8 *EFIAPI NetbufGetByte(IN NET_BUF *Nbuf, IN UINT32 Offset, OUT UINT32 *Index OPTIONAL)
Definition: NetBuffer.c:359
VOID EFIAPI UdpIoCleanIo(IN UDP_IO *UdpIo)
Definition: DxeUdpIoLib.c:915
EFI_STATUS EFIAPI UdpIoSendDatagram(IN UDP_IO *UdpIo, IN NET_BUF *Packet, IN UDP_END_POINT *EndPoint OPTIONAL, IN EFI_IP_ADDRESS *Gateway OPTIONAL, IN UDP_IO_CALLBACK CallBack, IN VOID *Context)
Definition: DxeUdpIoLib.c:971
EFI_STATUS EFIAPI UdpIoFreeIo(IN UDP_IO *UdpIo)
Definition: DxeUdpIoLib.c:809
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
@ TimerRelative
Definition: UefiSpec.h:539
UINT8 * ModeStr
Definition: Mtftp6.h:413
EFI_MTFTP6_TIMEOUT_CALLBACK TimeoutCallback
Definition: Mtftp6.h:450
EFI_MTFTP6_OPTION * OptionList
Definition: Mtftp6.h:425
UINT8 * Filename
Definition: Mtftp6.h:409
UINT32 OptionCount
Definition: Mtftp6.h:417
EFI_IP6_NEIGHBOR_CACHE * NeighborCache
Definition: Ip6.h:366
EFI_IP6_ICMP_TYPE * IcmpTypeList
Definition: Ip6.h:386
EFI_IP6_ADDRESS_INFO * AddressList
Definition: Ip6.h:336
EFI_IP6_ROUTE_TABLE * RouteTable
Definition: Ip6.h:356
EFI_IPv6_ADDRESS * GroupTable
Definition: Ip6.h:347
EFI_IP6_ADDRESS_INFO * PrefixTable
Definition: Ip6.h:376
BOOLEAN IsConfigured
Definition: Ip6.h:326
UINT16 InitialServerPort
Definition: Mtftp6.h:239
EFI_IPv6_ADDRESS ServerIp
Definition: Mtftp6.h:234
UINT8 ErrorMessage[1]
Definition: Mtftp6.h:197
UINT8 Filename[1]
Definition: Mtftp6.h:101
UINT16 StationPort
Definition: Udp6.h:168
BOOLEAN AcceptAnyPort
Definition: Udp6.h:126
UINT16 RemotePort
Definition: Udp6.h:182
BOOLEAN AcceptPromiscuous
Definition: Udp6.h:122
BOOLEAN AllowDuplicatePort
Definition: Udp6.h:131
EFI_IPv6_ADDRESS RemoteAddress
Definition: Udp6.h:175
UINT32 ReceiveTimeout
Definition: Udp6.h:144
UINT32 TransmitTimeout
Definition: Udp6.h:149
UINT8 TrafficClass
Definition: Udp6.h:135
EFI_IPv6_ADDRESS StationAddress
Definition: Udp6.h:161
EFI_MTFTP6_REQ_HEADER Rrq
Read request packet header.
Definition: Mtftp6.h:205
EFI_MTFTP6_ERROR_HEADER Error
Error packet header.
Definition: Mtftp6.h:212
UINT16 OpCode
Type of packets as defined by the MTFTPv6 packet opcodes.
Definition: Mtftp6.h:204