1 /* 2 * Copyright 1994, 1995, 2000 Neil Russell. 3 * (See License) 4 * Copyright 2000, 2001 DENX Software Engineering, Wolfgang Denk, wd@denx.de 5 */ 6 7 #include <common.h> 8 #include <command.h> 9 #include <net.h> 10 #include "tftp.h" 11 #include "bootp.h" 12 13 #undef ET_DEBUG 14 15 #if (CONFIG_COMMANDS & CFG_CMD_NET) 16 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 */ 21 #else 22 # define TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT * 2) 23 #endif 24 /* (for checking the image size) */ 25 #define HASHES_PER_LINE 65 /* Number of "loading" hashes per line */ 26 27 /* 28 * TFTP operations. 29 */ 30 #define TFTP_RRQ 1 31 #define TFTP_WRQ 2 32 #define TFTP_DATA 3 33 #define TFTP_ACK 4 34 #define TFTP_ERROR 5 35 36 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; 42 static int TftpState; 43 #define STATE_RRQ 1 44 #define STATE_DATA 2 45 #define STATE_TOO_LARGE 3 46 #define STATE_BAD_MAGIC 4 47 48 #define DEFAULT_NAME_LEN (8 + 4 + 1) 49 static char default_filename[DEFAULT_NAME_LEN]; 50 static char *tftp_filename; 51 52 #ifdef CFG_DIRECT_FLASH_TFTP 53 extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; 54 #endif 55 56 static __inline__ void 57 store_block (unsigned block, uchar * src, unsigned len) 58 { 59 ulong offset = block * 512, newsize = offset + len; 60 #ifdef CFG_DIRECT_FLASH_TFTP 61 int i, rc = 0; 62 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]) { 66 rc = 1; 67 break; 68 } 69 } 70 71 if (rc) { /* Flash is destination for this packet */ 72 rc = flash_write ((uchar *)src, (ulong)(load_addr+offset), len); 73 if (rc) { 74 flash_perror (rc); 75 NetState = NETLOOP_FAIL; 76 return; 77 } 78 } 79 else 80 #endif /* CFG_DIRECT_FLASH_TFTP */ 81 { 82 (void)memcpy((void *)(load_addr + offset), src, len); 83 } 84 85 if (NetBootFileXferSize < newsize) 86 NetBootFileXferSize = newsize; 87 } 88 89 static void TftpSend (void); 90 static void TftpTimeout (void); 91 92 /**********************************************************************/ 93 94 static void 95 TftpSend (void) 96 { 97 volatile uchar * pkt; 98 volatile uchar * xp; 99 int len = 0; 100 101 /* 102 * We will always be sending some sort of packet, so 103 * cobble together the packet headers now. 104 */ 105 pkt = NetTxPacket + ETHER_HDR_SIZE + IP_HDR_SIZE; 106 107 switch (TftpState) { 108 109 case STATE_RRQ: 110 xp = pkt; 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; 116 len = pkt - xp; 117 break; 118 119 case STATE_DATA: 120 xp = pkt; 121 *((ushort *)pkt)++ = htons(TFTP_ACK); 122 *((ushort *)pkt)++ = htons(TftpBlock); 123 len = pkt - xp; 124 break; 125 126 case STATE_TOO_LARGE: 127 xp = pkt; 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; 132 len = pkt - xp; 133 break; 134 135 case STATE_BAD_MAGIC: 136 xp = pkt; 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; 141 len = pkt - xp; 142 break; 143 } 144 145 NetSetEther (NetTxPacket, NetServerEther, PROT_IP); 146 NetSetIP (NetTxPacket + ETHER_HDR_SIZE, NetServerIP, 147 TftpServerPort, TftpOurPort, len); 148 NetSendPacket (NetTxPacket, ETHER_HDR_SIZE + IP_HDR_SIZE + len); 149 } 150 151 152 static void 153 TftpHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len) 154 { 155 ushort proto; 156 157 if (dest != TftpOurPort) { 158 return; 159 } 160 if (TftpState != STATE_RRQ && src != TftpServerPort) { 161 return; 162 } 163 164 if (len < 2) { 165 return; 166 } 167 len -= 2; 168 /* warning: don't use increment (++) in ntohs() macros!! */ 169 proto = *((ushort *)pkt)++; 170 switch (ntohs(proto)) { 171 172 case TFTP_RRQ: 173 case TFTP_WRQ: 174 case TFTP_ACK: 175 break; 176 default: 177 break; 178 179 case TFTP_DATA: 180 if (len < 2) 181 return; 182 len -= 2; 183 TftpBlock = ntohs(*(ushort *)pkt); 184 if (((TftpBlock - 1) % 10) == 0) { 185 putc ('#'); 186 } else if ((TftpBlock % (10 * HASHES_PER_LINE)) == 0) { 187 puts ("\n\t "); 188 } 189 190 if (TftpState == STATE_RRQ) { 191 TftpState = STATE_DATA; 192 TftpServerPort = src; 193 TftpLastBlock = 0; 194 195 if (TftpBlock != 1) { /* Assertion */ 196 printf ("\nTFTP error: " 197 "First block is not block 1 (%d)\n" 198 "Starting again\n\n", 199 TftpBlock); 200 NetStartAgain (); 201 break; 202 } 203 } 204 205 if (TftpBlock == TftpLastBlock) { 206 /* 207 * Same block again; ignore it. 208 */ 209 break; 210 } 211 212 TftpLastBlock = TftpBlock; 213 NetSetTimeout (TIMEOUT * CFG_HZ, TftpTimeout); 214 215 store_block (TftpBlock - 1, pkt + 2, len); 216 217 /* 218 * Acknoledge the block just received, which will prompt 219 * the server for the next one. 220 */ 221 TftpSend (); 222 223 if (len < 512) { 224 /* 225 * We received the whole thing. Try to 226 * run it. 227 */ 228 puts ("\ndone\n"); 229 NetState = NETLOOP_SUCCESS; 230 } 231 break; 232 233 case TFTP_ERROR: 234 printf ("\nTFTP error: '%s' (%d)\n", 235 pkt + 2, ntohs(*(ushort *)pkt)); 236 puts ("Starting again\n\n"); 237 NetStartAgain (); 238 break; 239 } 240 } 241 242 243 static void 244 TftpTimeout (void) 245 { 246 if (++TftpTimeoutCount >= TIMEOUT_COUNT) { 247 puts ("\nRetry count exceeded; starting again\n"); 248 NetStartAgain (); 249 } else { 250 puts ("T "); 251 NetSetTimeout (TIMEOUT * CFG_HZ, TftpTimeout); 252 TftpSend (); 253 } 254 } 255 256 257 void 258 TftpStart (void) 259 { 260 #ifdef ET_DEBUG 261 printf ("\nServer ethernet address %02x:%02x:%02x:%02x:%02x:%02x\n", 262 NetServerEther[0], 263 NetServerEther[1], 264 NetServerEther[2], 265 NetServerEther[3], 266 NetServerEther[4], 267 NetServerEther[5] 268 ); 269 #endif /* DEBUG */ 270 271 if (BootFile[0] == '\0') { 272 IPaddr_t OurIP = ntohl(NetOurIP); 273 274 sprintf(default_filename, "%02lX%02lX%02lX%02lX.img", 275 OurIP & 0xFF, 276 (OurIP >> 8) & 0xFF, 277 (OurIP >> 16) & 0xFF, 278 (OurIP >> 24) & 0xFF ); 279 tftp_filename = default_filename; 280 281 printf ("*** Warning: no boot file name; using '%s'\n", 282 tftp_filename); 283 } else { 284 tftp_filename = BootFile; 285 } 286 287 puts ("TFTP from server "); print_IPaddr (NetServerIP); 288 puts ("; our IP address is "); print_IPaddr (NetOurIP); 289 290 /* Check if we need to send across this subnet */ 291 if (NetOurGatewayIP && NetOurSubnetMask) { 292 IPaddr_t OurNet = NetOurIP & NetOurSubnetMask; 293 IPaddr_t ServerNet = NetServerIP & NetOurSubnetMask; 294 295 if (OurNet != ServerNet) { 296 puts ("; sending through gateway "); 297 print_IPaddr (NetOurGatewayIP) ; 298 } 299 } 300 putc ('\n'); 301 302 printf ("Filename '%s'.", tftp_filename); 303 304 if (NetBootFileSize) { 305 printf (" Size is 0x%x Bytes = ", NetBootFileSize<<9); 306 print_size (NetBootFileSize<<9, ""); 307 } 308 309 putc ('\n'); 310 311 printf ("Load address: 0x%lx\n", load_addr); 312 313 puts ("Loading: *\b"); 314 315 NetSetTimeout (TIMEOUT * CFG_HZ, TftpTimeout); 316 NetSetHandler (TftpHandler); 317 318 TftpServerPort = WELL_KNOWN_PORT; 319 TftpTimeoutCount = 0; 320 TftpState = STATE_RRQ; 321 TftpOurPort = 1024 + (get_timer(0) % 3072); 322 323 TftpSend (); 324 } 325 326 #endif /* CFG_CMD_NET */ 327