2 * Copyright 1994, 1995, 2000 Neil Russell.
4 * Copyright 2000, 2001 DENX Software Engineering, Wolfgang Denk, wd@denx.de
15 #if (CONFIG_COMMANDS & CFG_CMD_NET)
17 #define WELL_KNOWN_PORT 69 /* Well known TFTP port # */
18 #define TIMEOUT 2 /* Seconds to timeout for a lost pkt */
19 #ifndef CONFIG_NET_RETRY_COUNT
20 # define TIMEOUT_COUNT 10 /* # of timeouts before giving up */
22 # define TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT * 2)
24 /* (for checking the image size) */
25 #define HASHES_PER_LINE 65 /* Number of "loading" hashes per line */
37 static int TftpServerPort; /* The UDP port at their end */
38 static int TftpOurPort; /* The UDP port at our end */
39 static int TftpTimeoutCount;
40 static unsigned TftpBlock;
41 static unsigned TftpLastBlock;
45 #define STATE_TOO_LARGE 3
46 #define STATE_BAD_MAGIC 4
48 #define DEFAULT_NAME_LEN (8 + 4 + 1)
49 static char default_filename[DEFAULT_NAME_LEN];
50 static char *tftp_filename;
52 #ifdef CFG_DIRECT_FLASH_TFTP
53 extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
56 static __inline__ void
57 store_block (unsigned block, uchar * src, unsigned len)
59 ulong offset = block * 512, newsize = offset + len;
60 #ifdef CFG_DIRECT_FLASH_TFTP
63 for (i=0; i<CFG_MAX_FLASH_BANKS; i++) {
64 /* start address in flash? */
65 if (load_addr + offset >= flash_info[i].start[0]) {
71 if (rc) { /* Flash is destination for this packet */
72 rc = flash_write ((uchar *)src, (ulong)(load_addr+offset), len);
75 NetState = NETLOOP_FAIL;
80 #endif /* CFG_DIRECT_FLASH_TFTP */
82 (void)memcpy((void *)(load_addr + offset), src, len);
85 if (NetBootFileXferSize < newsize)
86 NetBootFileXferSize = newsize;
89 static void TftpSend (void);
90 static void TftpTimeout (void);
92 /**********************************************************************/
102 * We will always be sending some sort of packet, so
103 * cobble together the packet headers now.
105 pkt = NetTxPacket + ETHER_HDR_SIZE + IP_HDR_SIZE;
111 *((ushort *)pkt)++ = htons(TFTP_RRQ);
112 strcpy ((char *)pkt, tftp_filename);
113 pkt += strlen(tftp_filename) + 1;
114 strcpy ((char *)pkt, "octet");
115 pkt += 5 /*strlen("octet")*/ + 1;
121 *((ushort *)pkt)++ = htons(TFTP_ACK);
122 *((ushort *)pkt)++ = htons(TftpBlock);
126 case STATE_TOO_LARGE:
128 *((ushort *)pkt)++ = htons(TFTP_ERROR);
129 *((ushort *)pkt)++ = htons(3);
130 strcpy ((char *)pkt, "File too large");
131 pkt += 14 /*strlen("File too large")*/ + 1;
135 case STATE_BAD_MAGIC:
137 *((ushort *)pkt)++ = htons(TFTP_ERROR);
138 *((ushort *)pkt)++ = htons(2);
139 strcpy ((char *)pkt, "File has bad magic");
140 pkt += 18 /*strlen("File has bad magic")*/ + 1;
145 NetSendUDPPacket(NetServerEther, NetServerIP, TftpServerPort, TftpOurPort, len);
150 TftpHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len)
154 if (dest != TftpOurPort) {
157 if (TftpState != STATE_RRQ && src != TftpServerPort) {
165 /* warning: don't use increment (++) in ntohs() macros!! */
166 proto = *((ushort *)pkt)++;
167 switch (ntohs(proto)) {
180 TftpBlock = ntohs(*(ushort *)pkt);
181 if (((TftpBlock - 1) % 10) == 0) {
183 } else if ((TftpBlock % (10 * HASHES_PER_LINE)) == 0) {
187 if (TftpState == STATE_RRQ) {
188 TftpState = STATE_DATA;
189 TftpServerPort = src;
192 if (TftpBlock != 1) { /* Assertion */
193 printf ("\nTFTP error: "
194 "First block is not block 1 (%d)\n"
195 "Starting again\n\n",
202 if (TftpBlock == TftpLastBlock) {
204 * Same block again; ignore it.
209 TftpLastBlock = TftpBlock;
210 NetSetTimeout (TIMEOUT * CFG_HZ, TftpTimeout);
212 store_block (TftpBlock - 1, pkt + 2, len);
215 * Acknoledge the block just received, which will prompt
216 * the server for the next one.
222 * We received the whole thing. Try to
226 NetState = NETLOOP_SUCCESS;
231 printf ("\nTFTP error: '%s' (%d)\n",
232 pkt + 2, ntohs(*(ushort *)pkt));
233 puts ("Starting again\n\n");
243 if (++TftpTimeoutCount >= TIMEOUT_COUNT) {
244 puts ("\nRetry count exceeded; starting again\n");
248 NetSetTimeout (TIMEOUT * CFG_HZ, TftpTimeout);
257 if (BootFile[0] == '\0') {
258 IPaddr_t OurIP = ntohl(NetOurIP);
260 sprintf(default_filename, "%02lX%02lX%02lX%02lX.img",
263 (OurIP >> 16) & 0xFF,
264 (OurIP >> 24) & 0xFF );
265 tftp_filename = default_filename;
267 printf ("*** Warning: no boot file name; using '%s'\n",
270 tftp_filename = BootFile;
273 puts ("TFTP from server "); print_IPaddr (NetServerIP);
274 puts ("; our IP address is "); print_IPaddr (NetOurIP);
276 /* Check if we need to send across this subnet */
277 if (NetOurGatewayIP && NetOurSubnetMask) {
278 IPaddr_t OurNet = NetOurIP & NetOurSubnetMask;
279 IPaddr_t ServerNet = NetServerIP & NetOurSubnetMask;
281 if (OurNet != ServerNet) {
282 puts ("; sending through gateway ");
283 print_IPaddr (NetOurGatewayIP) ;
288 printf ("Filename '%s'.", tftp_filename);
290 if (NetBootFileSize) {
291 printf (" Size is 0x%x Bytes = ", NetBootFileSize<<9);
292 print_size (NetBootFileSize<<9, "");
297 printf ("Load address: 0x%lx\n", load_addr);
299 puts ("Loading: *\b");
301 NetSetTimeout (TIMEOUT * CFG_HZ, TftpTimeout);
302 NetSetHandler (TftpHandler);
304 TftpServerPort = WELL_KNOWN_PORT;
305 TftpTimeoutCount = 0;
306 TftpState = STATE_RRQ;
307 TftpOurPort = 1024 + (get_timer(0) % 3072);
309 /* zero out server ether in case the server ip has changed */
310 memset(NetServerEther, 0, 6);
315 #endif /* CFG_CMD_NET */