tftp.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  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. #include <common.h>
  7. #include <command.h>
  8. #include <net.h>
  9. #include "tftp.h"
  10. #include "bootp.h"
  11. #undef ET_DEBUG
  12. #if (CONFIG_COMMANDS & CFG_CMD_NET)
  13. #define WELL_KNOWN_PORT 69 /* Well known TFTP port # */
  14. #define TIMEOUT 2 /* Seconds to timeout for a lost pkt */
  15. #ifndef CONFIG_NET_RETRY_COUNT
  16. # define TIMEOUT_COUNT 10 /* # of timeouts before giving up */
  17. #else
  18. # define TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT * 2)
  19. #endif
  20. /* (for checking the image size) */
  21. #define HASHES_PER_LINE 65 /* Number of "loading" hashes per line */
  22. /*
  23. * TFTP operations.
  24. */
  25. #define TFTP_RRQ 1
  26. #define TFTP_WRQ 2
  27. #define TFTP_DATA 3
  28. #define TFTP_ACK 4
  29. #define TFTP_ERROR 5
  30. static int TftpServerPort; /* The UDP port at their end */
  31. static int TftpOurPort; /* The UDP port at our end */
  32. static int TftpTimeoutCount;
  33. static unsigned TftpBlock;
  34. static unsigned TftpLastBlock;
  35. static int TftpState;
  36. #define STATE_RRQ 1
  37. #define STATE_DATA 2
  38. #define STATE_TOO_LARGE 3
  39. #define STATE_BAD_MAGIC 4
  40. #define DEFAULT_NAME_LEN (8 + 4 + 1)
  41. static char default_filename[DEFAULT_NAME_LEN];
  42. static char *tftp_filename;
  43. #ifdef CFG_DIRECT_FLASH_TFTP
  44. extern flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
  45. #endif
  46. static __inline__ void
  47. store_block (unsigned block, uchar * src, unsigned len)
  48. {
  49. ulong offset = block * 512, newsize = offset + len;
  50. #ifdef CFG_DIRECT_FLASH_TFTP
  51. int i, rc = 0;
  52. for (i=0; i<CFG_MAX_FLASH_BANKS; i++) {
  53. /* start address in flash? */
  54. if (load_addr + offset >= flash_info[i].start[0]) {
  55. rc = 1;
  56. break;
  57. }
  58. }
  59. if (rc) { /* Flash is destination for this packet */
  60. rc = flash_write ((uchar *)src, (ulong)(load_addr+offset), len);
  61. if (rc) {
  62. flash_perror (rc);
  63. NetState = NETLOOP_FAIL;
  64. return;
  65. }
  66. }
  67. else
  68. #endif /* CFG_DIRECT_FLASH_TFTP */
  69. {
  70. (void)memcpy((void *)(load_addr + offset), src, len);
  71. }
  72. if (NetBootFileXferSize < newsize)
  73. NetBootFileXferSize = newsize;
  74. }
  75. static void TftpSend (void);
  76. static void TftpTimeout (void);
  77. /**********************************************************************/
  78. static void
  79. TftpSend (void)
  80. {
  81. volatile uchar * pkt;
  82. volatile uchar * xp;
  83. int len = 0;
  84. /*
  85. * We will always be sending some sort of packet, so
  86. * cobble together the packet headers now.
  87. */
  88. pkt = NetTxPacket + ETHER_HDR_SIZE + IP_HDR_SIZE;
  89. switch (TftpState) {
  90. case STATE_RRQ:
  91. xp = pkt;
  92. *((ushort *)pkt)++ = htons(TFTP_RRQ);
  93. strcpy ((char *)pkt, tftp_filename);
  94. pkt += strlen(tftp_filename) + 1;
  95. strcpy ((char *)pkt, "octet");
  96. pkt += 5 /*strlen("octet")*/ + 1;
  97. len = pkt - xp;
  98. break;
  99. case STATE_DATA:
  100. xp = pkt;
  101. *((ushort *)pkt)++ = htons(TFTP_ACK);
  102. *((ushort *)pkt)++ = htons(TftpBlock);
  103. len = pkt - xp;
  104. break;
  105. case STATE_TOO_LARGE:
  106. xp = pkt;
  107. *((ushort *)pkt)++ = htons(TFTP_ERROR);
  108. *((ushort *)pkt)++ = htons(3);
  109. strcpy ((char *)pkt, "File too large");
  110. pkt += 14 /*strlen("File too large")*/ + 1;
  111. len = pkt - xp;
  112. break;
  113. case STATE_BAD_MAGIC:
  114. xp = pkt;
  115. *((ushort *)pkt)++ = htons(TFTP_ERROR);
  116. *((ushort *)pkt)++ = htons(2);
  117. strcpy ((char *)pkt, "File has bad magic");
  118. pkt += 18 /*strlen("File has bad magic")*/ + 1;
  119. len = pkt - xp;
  120. break;
  121. }
  122. NetSendUDPPacket(NetServerEther, NetServerIP, TftpServerPort, TftpOurPort, len);
  123. }
  124. static void
  125. TftpHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len)
  126. {
  127. ushort proto;
  128. if (dest != TftpOurPort) {
  129. return;
  130. }
  131. if (TftpState != STATE_RRQ && src != TftpServerPort) {
  132. return;
  133. }
  134. if (len < 2) {
  135. return;
  136. }
  137. len -= 2;
  138. /* warning: don't use increment (++) in ntohs() macros!! */
  139. proto = *((ushort *)pkt)++;
  140. switch (ntohs(proto)) {
  141. case TFTP_RRQ:
  142. case TFTP_WRQ:
  143. case TFTP_ACK:
  144. break;
  145. default:
  146. break;
  147. case TFTP_DATA:
  148. if (len < 2)
  149. return;
  150. len -= 2;
  151. TftpBlock = ntohs(*(ushort *)pkt);
  152. if (((TftpBlock - 1) % 10) == 0) {
  153. putc ('#');
  154. } else if ((TftpBlock % (10 * HASHES_PER_LINE)) == 0) {
  155. puts ("\n\t ");
  156. }
  157. if (TftpState == STATE_RRQ) {
  158. TftpState = STATE_DATA;
  159. TftpServerPort = src;
  160. TftpLastBlock = 0;
  161. if (TftpBlock != 1) { /* Assertion */
  162. printf ("\nTFTP error: "
  163. "First block is not block 1 (%d)\n"
  164. "Starting again\n\n",
  165. TftpBlock);
  166. NetStartAgain ();
  167. break;
  168. }
  169. }
  170. if (TftpBlock == TftpLastBlock) {
  171. /*
  172. * Same block again; ignore it.
  173. */
  174. break;
  175. }
  176. TftpLastBlock = TftpBlock;
  177. NetSetTimeout (TIMEOUT * CFG_HZ, TftpTimeout);
  178. store_block (TftpBlock - 1, pkt + 2, len);
  179. /*
  180. * Acknoledge the block just received, which will prompt
  181. * the server for the next one.
  182. */
  183. TftpSend ();
  184. if (len < 512) {
  185. /*
  186. * We received the whole thing. Try to
  187. * run it.
  188. */
  189. puts ("\ndone\n");
  190. NetState = NETLOOP_SUCCESS;
  191. }
  192. break;
  193. case TFTP_ERROR:
  194. printf ("\nTFTP error: '%s' (%d)\n",
  195. pkt + 2, ntohs(*(ushort *)pkt));
  196. puts ("Starting again\n\n");
  197. NetStartAgain ();
  198. break;
  199. }
  200. }
  201. static void
  202. TftpTimeout (void)
  203. {
  204. if (++TftpTimeoutCount >= TIMEOUT_COUNT) {
  205. puts ("\nRetry count exceeded; starting again\n");
  206. NetStartAgain ();
  207. } else {
  208. puts ("T ");
  209. NetSetTimeout (TIMEOUT * CFG_HZ, TftpTimeout);
  210. TftpSend ();
  211. }
  212. }
  213. void
  214. TftpStart (void)
  215. {
  216. if (BootFile[0] == '\0') {
  217. IPaddr_t OurIP = ntohl(NetOurIP);
  218. sprintf(default_filename, "%02lX%02lX%02lX%02lX.img",
  219. OurIP & 0xFF,
  220. (OurIP >> 8) & 0xFF,
  221. (OurIP >> 16) & 0xFF,
  222. (OurIP >> 24) & 0xFF );
  223. tftp_filename = default_filename;
  224. printf ("*** Warning: no boot file name; using '%s'\n",
  225. tftp_filename);
  226. } else {
  227. tftp_filename = BootFile;
  228. }
  229. puts ("TFTP from server "); print_IPaddr (NetServerIP);
  230. puts ("; our IP address is "); print_IPaddr (NetOurIP);
  231. /* Check if we need to send across this subnet */
  232. if (NetOurGatewayIP && NetOurSubnetMask) {
  233. IPaddr_t OurNet = NetOurIP & NetOurSubnetMask;
  234. IPaddr_t ServerNet = NetServerIP & NetOurSubnetMask;
  235. if (OurNet != ServerNet) {
  236. puts ("; sending through gateway ");
  237. print_IPaddr (NetOurGatewayIP) ;
  238. }
  239. }
  240. putc ('\n');
  241. printf ("Filename '%s'.", tftp_filename);
  242. if (NetBootFileSize) {
  243. printf (" Size is 0x%x Bytes = ", NetBootFileSize<<9);
  244. print_size (NetBootFileSize<<9, "");
  245. }
  246. putc ('\n');
  247. printf ("Load address: 0x%lx\n", load_addr);
  248. puts ("Loading: *\b");
  249. NetSetTimeout (TIMEOUT * CFG_HZ, TftpTimeout);
  250. NetSetHandler (TftpHandler);
  251. TftpServerPort = WELL_KNOWN_PORT;
  252. TftpTimeoutCount = 0;
  253. TftpState = STATE_RRQ;
  254. TftpOurPort = 1024 + (get_timer(0) % 3072);
  255. /* zero out server ether in case the server ip has changed */
  256. memset(NetServerEther, 0, 6);
  257. TftpSend ();
  258. }
  259. #endif /* CFG_CMD_NET */