2 * Copyright 1994, 1995, 2000 Neil Russell.
4 * Copyright 2000, 2001 DENX Software Engineering, Wolfgang Denk, wd@denx.de
18 #define WELL_KNOWN_PORT 69 /* Well known TFTP port # */
19 #define TIMEOUT 5 /* Seconds to timeout for a lost pkt */
20 # define TIMEOUT_COUNT 10 /* # of timeouts before giving up */
21 /* (for checking the image size) */
22 #define HASHES_PER_LINE 65 /* Number of "loading" hashes per line */
35 static int TftpServerPort
; /* The UDP port at their end */
36 static int TftpOurPort
; /* The UDP port at our end */
37 static ulong TftpBlock
; /* packet sequence number */
38 static ulong TftpLastBlock
; /* last packet sequence number received */
39 static ulong TftpBlockWrap
; /* count of sequence number wraparounds */
40 static ulong TftpBlockWrapOffset
; /* memory offset due to wrapping */
47 #define TFTP_BLOCK_SIZE 512 /* default TFTP block size */
48 #define TFTP_SEQUENCE_SIZE ((ulong)(1<<16)) /* sequence number is 16 bit */
50 static char *tftp_filename
;
52 static int net_store_fd
;
54 static int store_block(unsigned block
, uchar
* src
, unsigned len
)
56 ulong offset
= block
* TFTP_BLOCK_SIZE
+ TftpBlockWrapOffset
;
57 ulong newsize
= offset
+ len
;
60 ret
= write(net_store_fd
, src
, len
);
64 if (NetBootFileXferSize
< newsize
)
65 NetBootFileXferSize
= newsize
;
69 static void TftpSend(void)
77 * We will always be sending some sort of packet, so
78 * cobble together the packet headers now.
80 pkt
= NetTxPacket
+ NetEthHdrSize() + IP_HDR_SIZE
;
86 *s
++ = htons(TFTP_RRQ
);
88 pkt
+= sprintf((uchar
*)pkt
, "%s%coctet%ctimeout%c%d",
89 tftp_filename
, 0, 0, 0, TIMEOUT
) + 1;
97 *s
++ = htons(TFTP_ACK
);
98 *s
++ = htons(TftpBlock
);
104 NetSendUDPPacket(NetServerEther
, NetServerIP
, TftpServerPort
,
108 static void TftpTimeout(void)
111 NetSetTimeout(TIMEOUT
* SECOND
, TftpTimeout
);
115 static void TftpHandler(uchar
* pkt
, unsigned dest
, unsigned src
, unsigned len
)
120 if (dest
!= TftpOurPort
)
123 if (TftpState
!= STATE_RRQ
&& src
!= TftpServerPort
)
130 /* warning: don't use increment (++) in ntohs() macros!! */
134 switch (ntohs(proto
)) {
143 debug("Got OACK: %s %s\n", pkt
, pkt
+strlen(pkt
)+1);
144 TftpState
= STATE_OACK
;
145 TftpServerPort
= src
;
146 TftpSend(); /* Send ACK */
152 TftpBlock
= ntohs(*(ushort
*)pkt
);
155 * RFC1350 specifies that the first data packet will
156 * have sequence number 1. If we receive a sequence
157 * number of 0 this means that there was a wrap
158 * around of the (16 bit) counter.
160 if (TftpBlock
== 0) {
162 TftpBlockWrapOffset
+= TFTP_BLOCK_SIZE
* TFTP_SEQUENCE_SIZE
;
163 printf ("\n\t %lu MB received\n\t ", TftpBlockWrapOffset
>>20);
165 if (((TftpBlock
- 1) % 10) == 0) {
167 } else if ((TftpBlock
% (10 * HASHES_PER_LINE
)) == 0) {
172 if (TftpState
== STATE_RRQ
)
173 debug("Server did not acknowledge timeout option!\n");
175 if (TftpState
== STATE_RRQ
|| TftpState
== STATE_OACK
) {
176 /* first block received */
177 TftpState
= STATE_DATA
;
178 TftpServerPort
= src
;
181 TftpBlockWrapOffset
= 0;
183 if (TftpBlock
!= 1) { /* Assertion */
184 printf("\nTFTP error: "
185 "First block is not block 1 (%ld)\n"
186 "Starting again\n\n",
188 NetState
= NETLOOP_FAIL
;
193 if (TftpBlock
== TftpLastBlock
)
194 /* Same block again; ignore it. */
197 TftpLastBlock
= TftpBlock
;
198 NetSetTimeout(TIMEOUT
* SECOND
, TftpTimeout
);
200 if (store_block(TftpBlock
- 1, pkt
+ 2, len
) < 0) {
202 NetState
= NETLOOP_FAIL
;
207 * Acknowledge the block just received, which will prompt
208 * the server for the next one.
212 if (len
< TFTP_BLOCK_SIZE
) {
214 * We received the whole thing. Try to
218 NetState
= NETLOOP_SUCCESS
;
223 printf("\nTFTP error: '%s' (%d)\n",
224 pkt
+ 2, ntohs(*(ushort
*)pkt
));
225 NetState
= NETLOOP_FAIL
;
230 void TftpStart(char *filename
)
232 char ip1
[16], ip2
[16];
234 tftp_filename
= filename
;
236 printf("TFTP from server %s; our IP address is %s\n"
237 "\nFilename '%s'.\nLoading: *\b",
238 ip_to_string(NetServerIP
, ip1
),
239 ip_to_string(NetOurIP
, ip2
),
242 NetSetTimeout(TIMEOUT
* SECOND
, TftpTimeout
);
243 NetSetHandler(TftpHandler
);
245 TftpServerPort
= WELL_KNOWN_PORT
;
246 TftpState
= STATE_RRQ
;
247 /* Use a pseudo-random port */
248 TftpOurPort
= 1024 + ((unsigned int)get_time_ns() % 3072);
251 /* zero out server ether in case the server ip has changed */
252 memset(NetServerEther
, 0, 6);
257 static int do_tftpb(struct command
*cmdtp
, int argc
, char *argv
[])
264 return COMMAND_ERROR_USAGE
;
266 remotefile
= argv
[1];
269 localfile
= basename(remotefile
);
273 net_store_fd
= open(localfile
, O_WRONLY
| O_CREAT
);
274 if (net_store_fd
< 0) {
279 if (NetLoopInit(TFTP
) < 0)
282 TftpStart(remotefile
);
289 /* NetLoop ok, update environment */
290 netboot_update_env();
297 static const __maybe_unused
char cmd_tftp_help
[] =
298 "Usage: tftp <file> [localfile]\n"
299 "Load a file via network using BootP/TFTP protocol.\n";
301 BAREBOX_CMD_START(tftp
)
303 .usage
= "Load file using tftp protocol",
304 BAREBOX_CMD_HELP(cmd_tftp_help
)
308 * @page tftp_command tftp
310 * Usage is: tftp \<filename\> [\<localfilename\>]
312 * Load a file via network using BootP/TFTP protocol. The loaded file you
313 * can find after download in you current ramdisk. Refer \b ls command.
315 * \<localfile> can be the local filename only, or also a device name. In the
316 * case of a device name, the will gets stored there. This works also for
317 * partitions of flash memory. Refer \b erase, \b unprotect for flash
320 * Note: This command is available only, if enabled in the menuconfig.