3 Copyright (c) 2006, 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.
17 TFTP and MTFTP (multicast TFTP) implementation.
23 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
26 // The following #define is used to create a version that does not wait to
27 // open after a listen. This is just for a special regression test of MTFTP
28 // server to make sure multiple opens are handled correctly. Normally this
29 // next line should be a comment.
30 // #define SpecialNowaitVersion // comment out for normal operation
33 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
38 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
73 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
77 PXE_BASECODE_DEVICE
*Private
,
82 EFI_IP_ADDRESS
*ServerIpPtr
,
83 EFI_PXE_BASE_CODE_UDP_PORT
*ServerPortPtr
,
84 EFI_IP_ADDRESS
*OurIpPtr
,
85 EFI_PXE_BASE_CODE_UDP_PORT
*OurPortPtr
,
90 Read TFTP packet. If TFTP ERROR packet is read, fill in TFTP error
91 information in Mode structure and return TFTP_ERROR status.
111 EFI_PXE_BASE_CODE_MODE
*PxeBcMode
;
113 EFI_EVENT TimeoutEvent
;
119 Status
= gBS
->CreateEvent (
127 if (EFI_ERROR (Status
)) {
131 Status
= gBS
->SetTimer (
134 Timeout
* 10000000 + 1000000
137 if (EFI_ERROR (Status
)) {
138 gBS
->CloseEvent (TimeoutEvent
);
144 HeaderSize
= Private
->BigBlkNumFlag
? sizeof (struct Tftpv4Ack8
) : sizeof (struct Tftpv4Ack
);
146 #define ERROR_MESSAGE_PTR ((struct Tftpv4Error *) HeaderPtr)
162 if (Status
!= EFI_SUCCESS
|| ERROR_MESSAGE_PTR
->OpCode
!= HTONS (TFTP_ERROR
)) {
163 gBS
->CloseEvent (TimeoutEvent
);
167 // got an error packet
168 // write one byte error code followed by error message
170 PxeBcMode
= Private
->EfiBc
.Mode
;
171 PxeBcMode
->TftpErrorReceived
= TRUE
;
172 PxeBcMode
->TftpError
.ErrorCode
= (UINT8
) NTOHS (ERROR_MESSAGE_PTR
->ErrCode
);
173 HeaderSize
= EFI_MIN (*BufferSizePtr
, sizeof PxeBcMode
->TftpError
.ErrorString
);
174 CopyMem (PxeBcMode
->TftpError
.ErrorString
, BufferPtr
, HeaderSize
);
176 gBS
->CloseEvent (TimeoutEvent
);
177 return EFI_TFTP_ERROR
;
180 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
184 PXE_BASECODE_DEVICE
*Private
,
185 EFI_IP_ADDRESS
*ServerIpPtr
,
186 EFI_PXE_BASE_CODE_UDP_PORT
*ServerPortPtr
,
187 EFI_PXE_BASE_CODE_UDP_PORT
*OurPortPtr
191 Send TFTP ERROR message to TFTP server
202 struct Tftpv4Error
*ErrStr
;
205 ErrStr
= (VOID
*) Private
->TftpErrorBuffer
;
206 Len
= sizeof *ErrStr
;
208 ErrStr
->OpCode
= HTONS (TFTP_ERROR
);
209 ErrStr
->ErrCode
= HTONS (TFTP_ERR_OPTION
);
210 ErrStr
->ErrMsg
[0] = 0;
214 EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT
,
227 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
231 PXE_BASECODE_DEVICE
*Private
,
232 EFI_IP_ADDRESS
*ServerIpPtr
,
233 EFI_PXE_BASE_CODE_UDP_PORT
*ServerPortPtr
,
234 EFI_IP_ADDRESS
*ReplyIpPtr
,
235 EFI_PXE_BASE_CODE_UDP_PORT
*OurPortPtr
,
244 Send TFTP ACK packet to server and read next DATA packet.
247 Private := Pointer to PxeBc interface
248 ServerIpPtr := Pointer to TFTP server IP address
249 ServerPortPtr := Pointer to TFTP server UDP port
250 ReplyIpPtr := Pointer to TFTP DATA packet destination IP address
251 OurPortPtr := Pointer to TFTP client UDP port
253 ReplyLenPtr := Pointer to packet length
254 PxeBcMode := Pointer to packet buffer
255 BlockNumPtr := Pointer to block number
256 AckOnly := TRUE == Send last ack - do not wait for reply
261 struct Tftpv4Data DataBuffer
;
262 struct Tftpv4Ack
*Ack2Ptr
;
263 struct Tftpv4Ack8
*Ack8Ptr
;
267 Ack2Ptr
= (VOID
*) Private
->TftpAckBuffer
;
268 Ack8Ptr
= (VOID
*) Private
->TftpAckBuffer
;
270 if (Private
->BigBlkNumFlag
) {
271 Len
= sizeof (struct Tftpv4Ack8
);
273 Ack8Ptr
->OpCode
= HTONS (TFTP_ACK8
);
274 Ack8Ptr
->BlockNum
= Swap64 (*BlockNumPtr
);
278 EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT
,
290 if (EFI_ERROR (Status
)) {
294 Len
= sizeof (struct Tftpv4Ack
);
296 Ack2Ptr
->OpCode
= HTONS (TFTP_ACK
);
297 Ack2Ptr
->BlockNum
= HTONS ((UINT16
) *BlockNumPtr
);
301 EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT
,
313 if (EFI_ERROR (Status
)) {
320 // ACK of last packet. This is just a courtesy.
321 // Do not wait for response.
328 Status
= TftpUdpRead (
341 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
345 // got a good reply (so far)
346 // check for next data packet
348 if (!Private
->BigBlkNumFlag
&& DataBuffer
.Header
.OpCode
== HTONS (TFTP_DATA
)) {
349 if (Status
== EFI_BUFFER_TOO_SMALL
) {
350 SendError (Private
, ServerIpPtr
, ServerPortPtr
, OurPortPtr
);
353 *BlockNumPtr
= NTOHS (DataBuffer
.Header
.BlockNum
);
357 if (Private
->BigBlkNumFlag
&& DataBuffer
.Header
.OpCode
== HTONS (TFTP_DATA8
)) {
358 if (Status
== EFI_BUFFER_TOO_SMALL
) {
359 SendError (Private
, ServerIpPtr
, ServerPortPtr
, OurPortPtr
);
362 *BlockNumPtr
= Swap64 (*(UINT64
*) &DataBuffer
.Header
.BlockNum
);
366 return EFI_PROTOCOL_ERROR
;
369 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
373 PXE_BASECODE_DEVICE
*Private
,
375 UINT64
*BufferSizePtr
,
378 EFI_IP_ADDRESS
*ServerIpPtr
,
379 EFI_PXE_BASE_CODE_UDP_PORT
*ServerPortPtr
,
380 EFI_IP_ADDRESS
*ReplyIpPtr
,
381 EFI_PXE_BASE_CODE_UDP_PORT
*OurPortPtr
,
384 IN BOOLEAN DontUseBuffer
388 Read rest of file after successfull M/TFTP request.
391 Private := Pointer to PxeBc interface
392 PacketSize := Pointer to packet size
393 BufferSizePtr := Pointer to buffer (file) size
394 Offset := Offset into buffer of next packet
395 BufferPtr := Pointer to receive buffer
396 ServerIpPtr := Pointer to TFTP server IP address
397 ServerPortPtr := Pointer to TFTP server UDP port
398 ReplyIpPtr := Pointer to TFTP DATA packet destination IP address
399 OurPortPtr := Pointer to TFTP client UDP port
400 LastBlock := Last block number received
402 DontUseBuffer := TRUE == throw away data, just count # of bytes
414 ReplyLen
= PacketSize
;
415 BlockNum
= LastBlock
;
417 DEBUG ((EFI_D_INFO
, "\nLockStepReceive() PacketSize = %d", PacketSize
));
420 BufferSize
= PacketSize
;
422 BufferSize
= *BufferSizePtr
- Offset
;
426 while (ReplyLen
>= 512 && ReplyLen
== PacketSize
) {
427 if (BufferSize
< PacketSize
) {
428 ReplyLen
= (UINTN
) ((BufferSize
> 0) ? BufferSize
: 0);
434 // write an ack packet and get data - retry up to NUM_ACK_RETRIES on timeout
436 Retries
= NUM_ACK_RETRIES
;
441 Status
= SendAckAndGetData (
454 if (!EFI_ERROR (Status
) || Status
== EFI_BUFFER_TOO_SMALL
) {
455 if (BlockNum
== LastBlock
) {
456 DEBUG ((EFI_D_NET
, "\nresend"));
458 // a resend - continue
460 Status
= EFI_TIMEOUT
;
461 } else if (Private
->BigBlkNumFlag
) {
462 if (BlockNum
!= ++LastBlock
) {
463 DEBUG ((EFI_D_NET
, "\nLockStepReceive() Exit #1a"));
465 // not correct blocknum - error
467 return EFI_PROTOCOL_ERROR
;
470 LastBlock
= (LastBlock
+ 1) & 0xFFFF;
471 if (BlockNum
!= LastBlock
) {
472 DEBUG ((EFI_D_NET
, "\nLockStepReceive() Exit #1b"));
473 return EFI_PROTOCOL_ERROR
;
475 // not correct blocknum - error
480 } while (Status
== EFI_TIMEOUT
&& --Retries
);
482 if (EFI_ERROR (Status
)) {
483 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
484 SendError (Private
, ServerIpPtr
, ServerPortPtr
, OurPortPtr
);
491 BufferSize
+= ReplyLen
;
493 BufferPtr
+= ReplyLen
;
494 BufferSize
-= ReplyLen
;
498 // while (ReplyLen == PacketSize);
501 if (BufferSizePtr
!= NULL
) {
502 *BufferSizePtr
= (BufferSize
- PacketSize
);
505 *BufferSizePtr
-= BufferSize
;
508 /* Send ACK of last packet. */
527 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
532 STATIC UINT8 Mode
[] = MODE_BINARY
;
533 STATIC UINT8 BlockSizeOp
[] = OP_BLKSIZE
;
534 STATIC UINT8 TsizeOp
[] = OP_TFRSIZE
;
535 STATIC UINT8 OverwriteOp
[] = OP_OVERWRITE
;
536 STATIC UINT8 BigBlkNumOp
[] = OP_BIGBLKNUM
;
537 STATIC EFI_PXE_BASE_CODE_UDP_PORT TftpRequestPort
= TFTP_OPEN_PORT
;
539 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
550 Check TFTP OACK packet for option.
553 OptionPtr := Pointer to option string to find
554 OpLen := Length of option string
555 OackPtr := Pointer to OACK data
556 OackSize := Length of OACK data
559 Pointer to value field if option found or NULL if not found.
562 if ((OackSize
-= OpLen
) <= 0) {
567 if (!CompareMem (OackPtr
, OptionPtr
, OpLen
)) {
568 return OackPtr
+ OpLen
;
572 } while (--OackSize
);
577 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
578 #define BKSZOP 1 // block size
579 #define TSIZEOP 2 // transfer size
580 #define OVERWRITEOP 4 // overwrite
581 #define BIGBLKNUMOP 8 // big block numbers
587 PXE_BASECODE_DEVICE
*Private
,
588 EFI_IP_ADDRESS
*ServerIpPtr
,
589 EFI_PXE_BASE_CODE_UDP_PORT
*ServerPortPtr
,
590 EFI_PXE_BASE_CODE_UDP_PORT
*OurPortPtr
,
592 UINTN
*PacketSizePtr
,
597 Send TFTP RRQ/WRQ packet.
600 Req := Type of request to send
601 Options := One or more of the #define values above
602 Private := Pointer to PxeBc interface
603 ServerIpPtr := Pointer to TFTP server IP address
604 ServerPortPtr := Pointer to TFTP server UDP port
605 OurPortPtr := Pointer to TFTP client UDP port
606 FilenamePtr := Pointer to TFTP file or directory name
607 PacketSizePtr := Pointer to block size
615 struct Tftpv4Req ReqStr
;
623 if (*OurPortPtr
== 0) {
624 OpFlags
= EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT
| EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
;
626 OpFlags
= EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT
;
629 // build the basic request - opcode, filename, mode
632 u
->ReqStr
.OpCode
= HTONS (Req
);
633 TotalLen
= sizeof (Mode
) + sizeof (u
->ReqStr
.OpCode
) + (Len
= 1 + AsciiStrLen ((CHAR8
*)FilenamePtr
));
635 CopyMem (u
->ReqStr
.FileName
, FilenamePtr
, Len
);
636 Ptr
= (UINT8
*) (u
->ReqStr
.FileName
+ Len
);
638 CopyMem (Ptr
, Mode
, sizeof (Mode
));
639 Ptr
+= sizeof (Mode
);
641 if (Options
& BKSZOP
) {
642 CopyMem (Ptr
, BlockSizeOp
, sizeof (BlockSizeOp
));
643 UtoA10 (*PacketSizePtr
, Ptr
+ sizeof (BlockSizeOp
));
645 TotalLen
+= (Len
= 1 + AsciiStrLen ((CHAR8
*)Ptr
+ sizeof (BlockSizeOp
)) + sizeof (BlockSizeOp
));
650 if (Options
& TSIZEOP
) {
651 CopyMem (Ptr
, TsizeOp
, sizeof (TsizeOp
));
652 CopyMem (Ptr
+ sizeof (TsizeOp
), "0", 2);
653 TotalLen
+= sizeof (TsizeOp
) + 2;
654 Ptr
+= sizeof (TsizeOp
) + 2;
657 if (Options
& OVERWRITEOP
) {
658 CopyMem (Ptr
, OverwriteOp
, sizeof (OverwriteOp
));
659 CopyMem (Ptr
+ sizeof (OverwriteOp
), "1", 2);
660 TotalLen
+= sizeof (OverwriteOp
) + 2;
661 Ptr
+= sizeof (OverwriteOp
) + 2;
664 if (Options
& BIGBLKNUMOP
) {
665 CopyMem (Ptr
, BigBlkNumOp
, sizeof (BigBlkNumOp
));
666 CopyMem (Ptr
+ sizeof (BigBlkNumOp
), "8", 2);
667 TotalLen
+= sizeof (BigBlkNumOp
) + 2;
668 Ptr
+= sizeof (BigBlkNumOp
) + 2;
688 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
694 PXE_BASECODE_DEVICE
*Private
,
696 UINTN
*PacketSizePtr
,
699 EFI_IP_ADDRESS
*ServerIpPtr
,
700 EFI_PXE_BASE_CODE_UDP_PORT
*ServerPortPtr
,
701 EFI_PXE_BASE_CODE_UDP_PORT
*ServerReplyPortPtr
,
702 EFI_PXE_BASE_CODE_UDP_PORT
*OurPortPtr
,
708 Start TFTP session. Issue request and wait for response.
709 Retry three times on error. If failed using options,
710 retry three times w/o options on error.
713 Req := TFTP request type
714 Options := TFTP option bits
715 Private := Pointer to PxeBc interface
717 PacketSizePtr := Pointer to block size
720 ServerIpPtr := Pointer to TFTP server IP address
721 ServerPortPtr := Pointer to TFTP server UDP port
722 ServerReplyPortPtr :=
723 OurPortPtr := Pointer to TFTP client UDP Port
724 FilenamePtr := Pointer to file or directory name
735 SaveReplyLen
= *ReplyLenPtr
;
737 Private
->BigBlkNumFlag
= FALSE
;
743 if (*OurPortPtr
!= 0) {
744 if (++ *OurPortPtr
== 0) {
745 *OurPortPtr
= PXE_RND_PORT_LOW
;
749 // send request from our Ip = StationIp
751 if ((Status
= TftpRwReq (
764 "\nTftpRwReqwResp() Exit #1 %xh (%r)",
772 // read reply to our Ip = StationIp
774 *ReplyLenPtr
= SaveReplyLen
;
776 Status
= TftpUdpRead (
778 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
788 } while (Status
== EFI_TIMEOUT
&& --Retries
);
790 if (!Options
|| Status
!= EFI_TFTP_ERROR
) {
793 "\nTftpRwReqwResp() Exit #2 %xh (%r)",
800 Status
= TftpRwReqwResp (
816 DEBUG ((EFI_D_WARN
, "\nTftpRwReqwResp() Exit #3 %xh (%r)", Status
, Status
));
821 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
825 // read on mcast ip, cport, from sport, for data packet
826 // returns success if gets multicast last packet or all up to last block
827 // if not missing, then finished
832 PXE_BASECODE_DEVICE
*Private
,
833 UINT64
*BufferSizePtr
,
835 EFI_IP_ADDRESS
*ServerIpPtr
,
836 EFI_PXE_BASE_CODE_MTFTP_INFO
*MtftpInfoPtr
,
837 UINT64
*StartBlockPtr
,
840 UINT16 ListenTimeout
,
842 IN BOOLEAN DontUseBuffer
846 Listen for MTFTP traffic and save desired packets.
849 Private := Pointer to PxeBc interface
852 ServerIpPtr := Pointer to TFTP server IP address
853 MtftpInfoPtr := Pointer to MTFTP session information
854 StartBlockPtr := IN=first block we are looking for OUT=first block received
855 NumMissedPtr := Number of blocks missed
859 DontUseBuffer := TRUE == throw packets away, just count bytes
865 struct Tftpv4Ack Header
;
876 LastBlockNum
= *StartBlockPtr
;
877 Timeout
= ListenTimeout
;
880 BufferSize
= *BufferSizePtr
;
881 ReplyLen
= MAX_TFTP_PKT_SIZE
;;
887 if ((SaveReplyLen
= ReplyLen
) > BufferSize
) {
888 SaveReplyLen
= (UINTN
) BufferSize
;
891 /* %%TBD - add big block number support */
894 // get data - loop on resends
897 ReplyLen
= SaveReplyLen
;
899 if ((Status
= TftpUdpRead (
906 &MtftpInfoPtr
->SPort
,
907 &MtftpInfoPtr
->MCastIp
,
908 &MtftpInfoPtr
->CPort
,
914 // make sure a data packet
916 if (Header
.OpCode
!= HTONS (TFTP_DATA
)) {
917 return EFI_PROTOCOL_ERROR
;
919 } while ((BlockNum
= NTOHS (Header
.BlockNum
)) == LastBlockNum
);
922 // make sure still going up
924 if (LastBlockNum
> BlockNum
) {
925 return EFI_PROTOCOL_ERROR
;
928 if (BlockNum
- LastBlockNum
> 0xFFFFFFFF) {
929 return EFI_PROTOCOL_ERROR
;
931 NumMissed
= (UINTN
) (BlockNum
- LastBlockNum
- 1);
934 LastBlockNum
= BlockNum
;
937 // if first time through, some reinitialization
940 *StartBlockPtr
= BlockNum
;
941 PacketSize
= ReplyLen
;
942 Timeout
= TransTimeout
;
944 *NumMissedPtr
= (UINT16
) (*NumMissedPtr
+ NumMissed
);
947 // if missed packets, update start block,
948 // etc. and move packet to proper place in buffer
951 *StartBlockPtr
= BlockNum
;
952 if (!DontUseBuffer
) {
953 Offset
= NumMissed
* PacketSize
;
954 CopyMem (BufferPtr
+ Offset
, BufferPtr
, ReplyLen
);
956 BufferSize
-= Offset
;
960 if (!DontUseBuffer
) {
961 BufferPtr
+= ReplyLen
;
962 BufferSize
-= ReplyLen
;
964 } while (ReplyLen
== PacketSize
&& BlockNum
!= FinalBlock
);
966 *BufferSizePtr
= BufferSize
;
971 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
975 PXE_BASECODE_DEVICE
* Private
,
976 UINT64
*BufferSizePtr
,
978 UINTN
*PacketSizePtr
,
979 EFI_IP_ADDRESS
* ServerIpPtr
,
981 EFI_PXE_BASE_CODE_MTFTP_INFO
* MtftpInfoPtr
,
982 UINT8
*CompletionStatusPtr
,
985 IN BOOLEAN DontUseBuffer
992 Private := Pointer to PxeBc interface
993 BufferSizePtr := IN=buffer size OUT=transfer size
999 CompletionStatusPtr :=
1003 // mtftp open session
1004 // return code EFI_SUCCESS
1005 // and *CompletionStatusPtr = GOTUNI | GOTMULTI means done
1006 // and *CompletionStatusPtr = GOTMULTI means got first two multicast packets, use listen for rest
1007 // and *CompletionStatusPtr = 0 means did not get first two multicast packets, use listen for all
1008 // (do not get = GOTUNI - returns NO_DATA go will go to TFTP session)
1012 EFI_IP_ADDRESS OurReplyIp
;
1013 struct Tftpv4Ack Header
;
1019 Retries
= NUM_MTFTP_OPEN_RETRIES
;
1020 BufferPtr2
= BufferPtr
;
1021 *PacketSizePtr
= (UINTN
) (EFI_MIN (*BufferSizePtr
, MAX_TFTP_PKT_SIZE
));
1025 // send a read request
1027 *CompletionStatusPtr
= 0;
1029 if ((Status
= TftpRwReq (
1034 &MtftpInfoPtr
->SPort
,
1035 &MtftpInfoPtr
->CPort
,
1039 )) != EFI_SUCCESS
) {
1047 ZeroMem (&OurReplyIp
, Private
->IpLength
);
1048 ReplyLen
= *PacketSizePtr
;
1050 if ((Status
= TftpUdpRead (
1052 EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER
,
1054 (UINTN
*) &ReplyLen
,
1057 &MtftpInfoPtr
->SPort
,
1059 &MtftpInfoPtr
->CPort
,
1060 MtftpInfoPtr
->TransmitTimeout
1061 )) == EFI_SUCCESS
) {
1063 // check for first data packet
1065 if (Header
.OpCode
!= HTONS (TFTP_DATA
)) {
1066 return EFI_PROTOCOL_ERROR
;
1071 if (Header
.BlockNum
!= HTONS (1)) {
1074 // if we are not the primary client,
1075 // we probably got first and now second
1076 // multicast but no unicast, so
1077 // *CompletionStatusPtr = GOTMULTI - if this is
1078 // the second, can just go on to listen
1079 // starting with 2 as the last block
1082 if (Header
.BlockNum
!= HTONS (2)) {
1086 *CompletionStatusPtr
= 0;
1095 *PacketSizePtr
= ReplyLen
;
1097 // see if a unicast data packet
1101 &Private
->EfiBc
.Mode
->StationIp
,
1104 *CompletionStatusPtr
|= GOTUNI
;
1107 // if already got multicast packet,
1110 if (*CompletionStatusPtr
& GOTMULTI
) {
1113 } else if (!CompareMem (
1115 &MtftpInfoPtr
->MCastIp
,
1119 // otherwise see if a multicast data packet
1121 *CompletionStatusPtr
|= GOTMULTI
;
1124 // got first - bump pointer so that if
1125 // second multi comes along, we're OK
1127 if (!DontUseBuffer
) {
1128 BufferPtr2
= (UINT8
*) BufferPtr
+ ReplyLen
;
1131 // if already got unicast packet,
1134 if (*CompletionStatusPtr
& GOTUNI
) {
1139 // else protocol error
1141 return EFI_PROTOCOL_ERROR
;
1143 } else if (Status
== EFI_TIMEOUT
) {
1145 // bad return code - if timed out, retry
1150 // else just bad - failed MTFTP open
1155 } while (Status
== EFI_TIMEOUT
&& --Retries
);
1157 if (Status
!= EFI_SUCCESS
) {
1164 // got em both - go into receive mode
1165 // routine to read rest of file after a successful open (TFTP or MTFTP)
1166 // sends ACK and gets next data packet until short packet arrives,
1167 // then sends ACK and (hopefully) times out
1169 return LockStepReceive (
1176 &MtftpInfoPtr
->SPort
,
1177 &MtftpInfoPtr
->MCastIp
,
1178 &MtftpInfoPtr
->CPort
,
1180 MtftpInfoPtr
->TransmitTimeout
,
1185 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1189 PXE_BASECODE_DEVICE
*Private
,
1190 UINT64
*BufferSizePtr
,
1192 EFI_IP_ADDRESS
*ServerIpPtr
,
1194 EFI_PXE_BASE_CODE_MTFTP_INFO
*MtftpInfoPtr
,
1195 IN BOOLEAN DontUseBuffer
1198 Routine description:
1202 // if did not get any packets, try MTFTP open
1203 // if got all packets, return
1204 // compute listen timeout and loop
1207 Private := Pointer to PxeBc interface
1218 EFI_PXE_BASE_CODE_IP_FILTER Filter
;
1222 UINT64 LastStartBlock
;
1226 UINT16 TransTimeout
;
1227 UINT16 ListenTimeout
;
1228 UINT8
*BufferPtrLocal
;
1230 TransTimeout
= MtftpInfoPtr
->TransmitTimeout
;
1231 ListenTimeout
= MtftpInfoPtr
->ListenTimeout
;
1236 Filter
.Filters
= EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST
;
1238 CopyMem (&Filter
.IpList
[0], &Private
->EfiBc
.Mode
->StationIp
, sizeof (EFI_IP_ADDRESS
));
1239 CopyMem (&Filter
.IpList
[1], &MtftpInfoPtr
->MCastIp
, sizeof (EFI_IP_ADDRESS
));
1241 if ((Status
= IpFilter (Private
, &Filter
)) != EFI_SUCCESS
) {
1246 StartBlock
= LastStartBlock
;
1247 BufferSize
= *BufferSizePtr
- Offset
;
1249 if (DontUseBuffer
) {
1251 // overwrie the temp buf
1253 BufferPtrLocal
= BufferPtr
;
1255 BufferPtrLocal
= BufferPtr
+ Offset
;
1259 // special !!! do not leave enabled in saved version on Source Safe
1260 // Following code put in in order to create a special version for regression
1261 // test of MTFTP server to make sure it handles mulitple opens correctly.
1262 // This code should NOT be enabled normally.
1264 #ifdef SpecialNowaitVersion
1265 #pragma message ("This is special version for MTFTP regression test")
1266 if (StartBlock
|| !LastBlock
)
1268 if (((Status
= MtftpListen (
1280 )) != EFI_SUCCESS
) && (Status
!= EFI_TIMEOUT
)) {
1287 // if none were received, start block is not reset
1289 if (StartBlock
== LastStartBlock
) {
1293 // timed out with none received - try MTFTP open
1295 if ((Status
= MtftpOpen (
1305 )) != EFI_SUCCESS
) {
1307 // open failure - try TFTP
1312 // return code EFI_SUCCESS
1313 // and *CompletionStatusPtr = GOTUNI | GOTMULTI means done
1314 // and *CompletionStatusPtr = GOTMULTI means got first two multicast packets, use listen for rest
1315 // and *CompletionStatusPtr = 0 means did not get first two multicast packets, use listen for all
1316 // (do not get = GOTUNI - returns NO_DATA go will go to TFTP session)
1318 if (CompStat
== (GOTUNI
| GOTMULTI
)) {
1320 // finished - got it all
1327 // offset is two packet lengths
1331 // last block received
1339 ListenTimeout
= TransTimeout
;
1343 // did we get the last block
1345 if (Status
== EFI_SUCCESS
) {
1347 // yes - set the file size if this was first time
1350 *BufferSizePtr
-= BufferSize
;
1353 // if buffer was too small, finished
1355 if (!DontUseBuffer
) {
1356 return EFI_BUFFER_TOO_SMALL
;
1359 // if we got them all, finished
1361 if (!NumMissed
&& StartBlock
== LastStartBlock
+ 1) {
1365 // did not get them all - set last block
1367 LastBlock
= (UINT16
) (StartBlock
- 1);
1370 // compute listen timeout
1372 ListenTimeout
= (UINT16
) ((NumMissed
> MtftpInfoPtr
->ListenTimeout
) ? 0 : (MtftpInfoPtr
->ListenTimeout
- NumMissed
));
1382 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1386 PXE_BASECODE_DEVICE
*Private
,
1387 UINT64
*BufferSizePtr
,
1388 EFI_IP_ADDRESS
*ServerIpPtr
,
1389 EFI_PXE_BASE_CODE_UDP_PORT SrvPort
,
1391 UINTN
*PacketSizePtr
1394 Routine description:
1395 // TFTP info request routine
1396 // send read request with block size and transfer size options
1398 // send error to terminate session
1399 // if OACK received, set info
1412 EFI_PXE_BASE_CODE_UDP_PORT OurPort
;
1413 EFI_PXE_BASE_CODE_UDP_PORT ServerReplyPort
;
1421 struct Tftpv4Oack OAck2Ptr
;
1422 struct Tftpv4Ack Ack2Ptr
;
1423 struct Tftpv4Data Datastr
;
1427 ServerReplyPort
= 0;
1428 ReplyLen
= sizeof (u
.Datastr
.Data
);
1431 // send a write request with the blocksize option -
1432 // sets our IP and port - and receive reply - sets his port
1433 // will retry operation up to 3 times if no response,
1434 // and will retry without options on an error reply
1436 if ((Status
= TftpRwReqwResp (
1438 /* BIGBLKNUMOP | */BKSZOP
| TSIZEOP
,
1450 )) != EFI_SUCCESS
) {
1451 DEBUG ((EFI_D_WARN
, "\nTftpInfo() Exit #1"));
1455 // check for good OACK
1457 if (u
.OAck2Ptr
.OpCode
== HTONS (TFTP_OACK
)) {
1459 // now parse it for options
1464 sizeof (BigBlkNumOp
),
1465 u
.OAck2Ptr
.OpAck
[0].Option
,
1466 ReplyLen
+ sizeof (u
.Ack2Ptr
.BlockNum
)
1470 if (AtoU (Ptr
) == 8) {
1471 Private
->BigBlkNumFlag
= TRUE
;
1473 return EFI_PROTOCOL_ERROR
;
1481 sizeof (BlockSizeOp
),
1482 u
.OAck2Ptr
.OpAck
[0].Option
,
1483 ReplyLen
+= sizeof (u
.Ack2Ptr
.BlockNum
)
1486 *PacketSizePtr
= (Ptr
) ? AtoU (Ptr
) : 512;
1494 u
.OAck2Ptr
.OpAck
[0].Option
,
1499 *BufferSizePtr
= AtoU64 (Ptr
);
1502 // teminate session with error
1504 SendError (Private
, ServerIpPtr
, &ServerReplyPort
, &OurPort
);
1513 // if MTFTP get filesize, return unsupported
1515 if (SrvPort
!= TftpRequestPort
) {
1516 SendError (Private
, ServerIpPtr
, &ServerReplyPort
, &OurPort
);
1517 DEBUG ((EFI_D_WARN
, "\nTftpInfo() Exit #3"));
1518 return EFI_UNSUPPORTED
;
1523 // last block received
1528 // does not support the option - do a download with no buffer
1532 Status
= LockStepReceive (
1540 &Private
->EfiBc
.Mode
->StationIp
,
1547 if (Status
!= EFI_SUCCESS
) {
1548 DEBUG ((EFI_D_WARN
, "\nTftpInfo() LockStepReceive() == %Xh", Status
));
1551 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1558 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1562 PXE_BASECODE_DEVICE
*Private
,
1563 UINT64
*BufferSizePtr
,
1565 EFI_IP_ADDRESS
*ServerIpPtr
,
1567 UINTN
*PacketSizePtr
,
1568 EFI_PXE_BASE_CODE_UDP_PORT SrvPort
,
1570 IN BOOLEAN DontUseBuffer
1573 Routine description:
1574 // tftp read session
1575 // send read request
1581 // while data size is max
1597 EFI_PXE_BASE_CODE_UDP_PORT OurPort
;
1598 EFI_PXE_BASE_CODE_UDP_PORT ServerReplyPort
;
1606 struct Tftpv4Ack Ack2Ptr
;
1607 struct Tftpv4Oack OAck2Ptr
;
1608 struct Tftpv4Data Data
;
1609 struct Tftpv4Ack8 Ack8Ptr
;
1610 struct Tftpv4Data8 Data8
;
1614 ServerReplyPort
= 0;
1615 ReplyLen
= (UINTN
) ((*BufferSizePtr
> 0xFFFF) ? 0xFFFF : *BufferSizePtr
);
1618 // send a read request with the blocksize option - sets our IP and port
1619 // - and receive reply - sets his port will retry operation up to 3
1620 // times if no response, and will retry without options on an error
1623 if ((Status
= TftpRwReqwResp (
1625 /* BIGBLKNUMOP | */BKSZOP
,
1637 )) != EFI_SUCCESS
) {
1638 DEBUG ((EFI_D_WARN
, "\nTftpDownload() Exit #1 %xh (%r)", Status
, Status
));
1644 if (U
.OAck2Ptr
.OpCode
== HTONS (TFTP_OACK
)) {
1648 CopyMem (U
.Data
.Data
, BufferPtr
, ReplyLen
);
1652 sizeof (BigBlkNumOp
),
1653 U
.OAck2Ptr
.OpAck
[0].Option
,
1654 ReplyLen
+ sizeof (U
.Ack2Ptr
.BlockNum
)
1658 if (AtoU (Ptr
) == 8) {
1659 Private
->BigBlkNumFlag
= TRUE
;
1661 return EFI_PROTOCOL_ERROR
;
1665 // now parse it for blocksize option
1669 sizeof (BlockSizeOp
),
1670 U
.OAck2Ptr
.OpAck
[0].Option
,
1671 ReplyLen
+= sizeof (U
.Ack2Ptr
.BlockNum
)
1674 ReplyLen
= (Ptr
!= NULL
) ? AtoU (Ptr
) : 512;
1678 // last block received
1681 } else if (U
.Ack2Ptr
.OpCode
!= HTONS (TFTP_DATA
) || U
.Ack2Ptr
.BlockNum
!= HTONS (1)) {
1685 DEBUG ((EFI_D_WARN
, "\nTftpDownload() Exit #2 %xh (%r)", Status
, Status
));
1687 return EFI_PROTOCOL_ERROR
;
1690 // got good data packet
1694 // last block received
1699 if (PacketSizePtr
!= NULL
) {
1700 *PacketSizePtr
= ReplyLen
;
1703 // routine to read rest of file after a successful open (TFTP or MTFTP)
1704 // sends ACK and gets next data packet until short packet arrives, then sends
1705 // ACK and (hopefully) times out
1706 // if first packet has been read, BufferPtr and BufferSize must reflect fact
1708 Status
= LockStepReceive (
1716 &Private
->EfiBc
.Mode
->StationIp
,
1723 if (Status
!= EFI_SUCCESS
) {
1724 DEBUG ((EFI_D_WARN
, "\nTftpDownload() Exit #3 %xh (%r)", Status
, Status
));
1726 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1736 if (!EFI_ERROR (Status
)) {
1737 Status
= EFI_BUFFER_TOO_SMALL
;
1745 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1749 PXE_BASECODE_DEVICE
*Private
,
1750 UINT64
*BufferSizePtr
,
1752 EFI_IP_ADDRESS
*ServerIpPtr
,
1754 UINTN
*PacketSizePtr
,
1758 Routine description:
1759 // tftp write session
1760 // send write request
1763 // send min (rest of data, max data packet)
1765 // while data size is max
1779 struct Tftpv4Ack Header
;
1780 EFI_PXE_BASE_CODE_UDP_PORT OurPort
;
1781 EFI_PXE_BASE_CODE_UDP_PORT ServerReplyPort
;
1784 UINT64 TransferSize
;
1791 struct Tftpv4Oack OAck2Ptr
;
1792 struct Tftpv4Ack Ack2Ptr
;
1793 struct Tftpv4Data Datastr
;
1797 ServerReplyPort
= 0;
1798 TransferSize
= *BufferSizePtr
;
1799 ReplyLen
= sizeof (u
.Datastr
.Data
);
1800 Options
= (UINT16
) ((Overwrite
) ? OVERWRITEOP
| BKSZOP
: BKSZOP
);
1803 // send a write request with the blocksize option - sets our IP and port -
1804 // and receive reply - sets his port
1805 // will retry operation up to 3 times if no response, and will retry without
1806 // options on an error reply
1808 if ((Status
= TftpRwReqwResp (
1822 )) != EFI_SUCCESS
) {
1828 if (u
.OAck2Ptr
.OpCode
== HTONS (TFTP_OACK
)) {
1830 // parse it for blocksize option
1834 sizeof (BlockSizeOp
),
1835 u
.OAck2Ptr
.OpAck
[0].Option
,
1836 ReplyLen
+= sizeof (u
.Ack2Ptr
.BlockNum
)
1838 *PacketSizePtr
= (Ptr
) ? AtoU (Ptr
) : 512;
1843 else if (u
.Ack2Ptr
.OpCode
== HTONS (TFTP_ACK
)) {
1845 // option was not supported
1847 *PacketSizePtr
= 512;
1849 return EFI_PROTOCOL_ERROR
;
1854 Header
.OpCode
= HTONS (TFTP_DATA
);
1856 Header
.BlockNum
= HTONS (1);
1862 Retries
= NUM_ACK_RETRIES
;
1863 HeaderSize
= sizeof (Header
);
1864 TransferLen
= (UINTN
) (EFI_MIN (*PacketSizePtr
, TransferSize
));
1867 // write a data packet and get an ack
1873 if ((Status
= UdpWrite (
1875 EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT
,
1885 )) != EFI_SUCCESS
) {
1891 ReplyLen
= sizeof (u
.Datastr
.Data
);
1893 if ((Status
= TftpUdpRead (
1904 )) == EFI_SUCCESS
) {
1906 // check for ACK for this data packet
1908 if (u
.Ack2Ptr
.OpCode
!= HTONS (TFTP_ACK
)) {
1909 return EFI_PROTOCOL_ERROR
;
1912 if (u
.Ack2Ptr
.BlockNum
!= Header
.BlockNum
) {
1914 // not for this packet - continue
1916 Status
= EFI_TIMEOUT
;
1919 } while (Status
== EFI_TIMEOUT
&& --Retries
);
1921 if (Status
!= EFI_SUCCESS
) {
1925 BufferPtr
= (VOID
*) ((UINT8
*) (BufferPtr
) + TransferLen
);
1926 TransferSize
-= TransferLen
;
1928 Header
.BlockNum
= HTONS ((UINT16
) BlockNum
);
1929 } while (TransferLen
== *PacketSizePtr
);
1934 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1938 PXE_BASECODE_DEVICE
*Private
,
1939 IN EFI_PXE_BASE_CODE_TFTP_OPCODE Operation
,
1940 UINT64
*BufferSizePtr
,
1942 EFI_IP_ADDRESS
*ServerIpPtr
,
1944 UINTN
*PacketSizePtr
,
1945 IN EFI_PXE_BASE_CODE_MTFTP_INFO
*MtftpInfoPtr
, OPTIONAL
1946 IN BOOLEAN Overwrite
,
1947 IN BOOLEAN DontUseBuffer
1950 Routine description:
1951 MTFTP API entry point
1966 * EFI_INVALID_PARAMETER
1967 * EFI_OUT_OF_RESOURCES
1968 * EFI_BAD_BUFFER_SIZE
1969 * Status is also returned from IpFilter(), TftpInfo(), MtftpDownload(),
1970 * TftpDownload() and TftpUpload().
1973 EFI_PXE_BASE_CODE_IP_FILTER Filter
;
1974 EFI_STATUS StatCode
;
1976 UINT64 BufferSizeLocal
;
1978 UINT8
*BufferPtrLocal
;
1980 Filter
.Filters
= EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
;
1982 Filter
.reserved
= 0;
1984 /* No error has occurred, yet. */
1985 Private
->EfiBc
.Mode
->TftpErrorReceived
= FALSE
;
1987 /* We must at least have an MTFTP server IP address and
1988 * a pointer to the buffer size.
1990 if (!ServerIpPtr
|| !BufferSizePtr
) {
1991 DEBUG ((EFI_D_WARN
, "\nPxeBcMtftp() Exit #1"));
1993 return EFI_INVALID_PARAMETER
;
1996 Private
->Function
= EFI_PXE_BASE_CODE_FUNCTION_MTFTP
;
1999 // make sure filter set to unicast at start
2001 if ((StatCode
= IpFilter (Private
, &Filter
)) != EFI_SUCCESS
) {
2004 "\nPxeBcMtftp() Exit IpFilter() == %Xh",
2011 // set unset parms to default values
2013 if (!PacketSizePtr
) {
2014 *(PacketSizePtr
= &PacketSize
) = MAX_TFTP_PKT_SIZE
;
2017 if (*PacketSizePtr
> *BufferSizePtr
) {
2018 *PacketSizePtr
= (UINTN
) *BufferSizePtr
;
2021 if (*PacketSizePtr
< MIN_TFTP_PKT_SIZE
) {
2022 *PacketSizePtr
= MIN_TFTP_PKT_SIZE
;
2025 if (*PacketSizePtr
> BUFFER_ALLOCATE_SIZE
) {
2026 *PacketSizePtr
= BUFFER_ALLOCATE_SIZE
;
2029 if (*PacketSizePtr
> MAX_TFTP_PKT_SIZE
) {
2030 *PacketSizePtr
= MAX_TFTP_PKT_SIZE
;
2033 if (Operation
== EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE
) {
2034 StatCode
= TftpInfo (
2043 if (StatCode
!= EFI_SUCCESS
) {
2046 "\nPxeBcMtftp() Exit TftpInfo() == %Xh",
2054 if (Operation
== EFI_PXE_BASE_CODE_MTFTP_GET_FILE_SIZE
) {
2055 if (!MtftpInfoPtr
|| !MtftpInfoPtr
->SPort
) {
2056 DEBUG ((EFI_D_WARN
, "\nPxeBcMtftp() Exit #2"));
2057 return EFI_INVALID_PARAMETER
;
2059 StatCode
= TftpInfo (
2063 MtftpInfoPtr
->SPort
,
2070 if (StatCode
!= EFI_SUCCESS
) {
2073 "\nPxeBcMtftp() Exit TftpInfo() == %Xh",
2082 if (!BufferPtr
&& !DontUseBuffer
) {
2084 // if dontusebuffer is false and no buffer???
2086 DEBUG ((EFI_D_WARN
, "\nPxeBcMtftp() Exit #3"));
2088 // DontUseBuffer can be true only for read_file operation
2090 return EFI_INVALID_PARAMETER
;
2093 if (DontUseBuffer
) {
2094 Status
= gBS
->AllocatePool (
2095 EfiBootServicesData
,
2096 BUFFER_ALLOCATE_SIZE
,
2097 (VOID
**) &BufferPtrLocal
2100 if (EFI_ERROR (Status
) || BufferPtrLocal
== NULL
) {
2101 DEBUG ((EFI_D_NET
, "\nPxeBcMtftp() Exit #4"));
2102 return EFI_OUT_OF_RESOURCES
;
2105 BufferSizeLocal
= BUFFER_ALLOCATE_SIZE
;
2107 if (!*BufferSizePtr
&& Operation
!= EFI_PXE_BASE_CODE_TFTP_WRITE_FILE
) {
2108 DEBUG ((EFI_D_WARN
, "\nPxeBcMtftp() Exit #5"));
2109 return EFI_BAD_BUFFER_SIZE
;
2112 BufferPtrLocal
= BufferPtr
;
2113 BufferSizeLocal
= *BufferSizePtr
;
2116 switch (Operation
) {
2117 case EFI_PXE_BASE_CODE_MTFTP_READ_FILE
:
2118 if (FilenamePtr
== NULL
||
2119 MtftpInfoPtr
== NULL
||
2120 MtftpInfoPtr
->MCastIp
.Addr
[0] == 0 ||
2121 MtftpInfoPtr
->SPort
== 0 ||
2122 MtftpInfoPtr
->CPort
== 0 ||
2123 MtftpInfoPtr
->ListenTimeout
== 0 ||
2124 MtftpInfoPtr
->TransmitTimeout
== 0
2126 StatCode
= EFI_INVALID_PARAMETER
;
2130 // try MTFTP - if fails, drop into TFTP read
2132 if ((StatCode
= MtftpDownload (
2140 )) == EFI_SUCCESS
|| StatCode
== EFI_BUFFER_TOO_SMALL
) {
2141 if (BufferSizePtr
/* %% !DontUseBuffer */ ) {
2142 *BufferSizePtr
= BufferSizeLocal
;
2148 // go back to unicast
2150 if ((StatCode
= IpFilter (Private
, &Filter
)) != EFI_SUCCESS
) {
2155 case EFI_PXE_BASE_CODE_TFTP_READ_FILE
:
2156 if (FilenamePtr
== NULL
) {
2157 StatCode
= EFI_INVALID_PARAMETER
;
2161 StatCode
= TftpDownload (
2173 if (StatCode
== EFI_SUCCESS
|| StatCode
== EFI_BUFFER_TOO_SMALL
) {
2174 if (BufferSizePtr
/* !DontUseBuffer */ ) {
2175 *BufferSizePtr
= BufferSizeLocal
;
2181 case EFI_PXE_BASE_CODE_TFTP_WRITE_FILE
:
2182 if (FilenamePtr
== NULL
|| DontUseBuffer
) {
2184 // not a valid option
2186 StatCode
= EFI_INVALID_PARAMETER
;
2190 StatCode
= TftpUpload (
2200 if (StatCode
!= EFI_SUCCESS
) {
2203 "\nPxeBcMtftp() Exit #6 %xh (%r)",
2211 case EFI_PXE_BASE_CODE_TFTP_READ_DIRECTORY
:
2212 if (FilenamePtr
== NULL
|| DontUseBuffer
) {
2214 // not a valid option
2216 StatCode
= EFI_INVALID_PARAMETER
;
2220 StatCode
= TftpDownload (
2232 if (StatCode
!= EFI_SUCCESS
) {
2235 "\nPxeBcMtftp() Exit #7 %xh (%r)",
2243 case EFI_PXE_BASE_CODE_MTFTP_READ_DIRECTORY
:
2244 if (DontUseBuffer
) {
2245 StatCode
= EFI_INVALID_PARAMETER
;
2249 if (MtftpInfoPtr
== NULL
|| !MtftpInfoPtr
->SPort
) {
2252 "\nPxeBcMtftp() Exit #9 %xh (%r)",
2253 EFI_INVALID_PARAMETER
,
2254 EFI_INVALID_PARAMETER
)
2257 return EFI_INVALID_PARAMETER
;
2260 StatCode
= TftpDownload (
2267 MtftpInfoPtr
->SPort
,
2275 StatCode
= EFI_INVALID_PARAMETER
;
2278 if (DontUseBuffer
) {
2279 gBS
->FreePool (BufferPtrLocal
);
2282 if (StatCode
!= EFI_SUCCESS
) {
2285 "\nPxeBcMtftp() Exit #8 %xh (%r)",
2296 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2300 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
2301 IN EFI_PXE_BASE_CODE_TFTP_OPCODE Operation
,
2302 IN OUT VOID
*BufferPtr
,
2303 IN BOOLEAN Overwrite
,
2304 IN OUT UINT64
*BufferSizePtr
,
2305 IN UINTN
*BlockSizePtr OPTIONAL
,
2306 IN EFI_IP_ADDRESS
* ServerIpPtr
,
2307 IN UINT8
*FilenamePtr
,
2308 IN EFI_PXE_BASE_CODE_MTFTP_INFO
* MtftpInfoPtr OPTIONAL
,
2309 IN BOOLEAN DontUseBuffer
2312 Routine description:
2313 MTFTP API entry point.
2328 * EFI_INVALID_PARAMETER
2329 * Status is also returned from PxeBcMtftp();
2332 EFI_PXE_BASE_CODE_IP_FILTER Filter
;
2333 EFI_STATUS StatCode
;
2334 PXE_BASECODE_DEVICE
*Private
;
2337 // Lock the instance data and make sure started
2339 StatCode
= EFI_SUCCESS
;
2342 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
2343 return EFI_INVALID_PARAMETER
;
2346 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
2348 if (Private
== NULL
) {
2349 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
2350 return EFI_INVALID_PARAMETER
;
2353 EfiAcquireLock (&Private
->Lock
);
2355 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
2356 DEBUG ((EFI_D_ERROR
, "BC was not started."));
2357 EfiReleaseLock (&Private
->Lock
);
2358 return EFI_NOT_STARTED
;
2363 Filter
.Filters
= EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
;
2365 Filter
.reserved
= 0;
2367 DEBUG ((EFI_D_WARN
, "\nBcMtftp() Op=%d Buf=%Xh", Operation
, BufferPtr
));
2369 StatCode
= PxeBcMtftp (
2383 // restore to unicast
2385 IpFilter (Private
, &Filter
);
2388 // Unlock the instance data
2390 EfiReleaseLock (&Private
->Lock
);
2394 /* eof - PxeBcMtftp.c */