uboot/net/tftp.c
<<
>>
Prefs
   1/*
   2 * Copyright 1994, 1995, 2000 Neil Russell.
   3 * (See License)
   4 * Copyright 2000, 2001 DENX Software Engineering, Wolfgang Denk, wd@denx.de
   5 * Copyright 2011 Comelit Group SpA,
   6 *                Luca Ceresoli <luca.ceresoli@comelit.it>
   7 */
   8
   9#include <common.h>
  10#include <command.h>
  11#include <net.h>
  12#include "tftp.h"
  13#include "bootp.h"
  14
  15/* Well known TFTP port # */
  16#define WELL_KNOWN_PORT 69
  17/* Millisecs to timeout for lost pkt */
  18#define TIMEOUT         5000UL
  19#ifndef CONFIG_NET_RETRY_COUNT
  20/* # of timeouts before giving up */
  21# define TIMEOUT_COUNT  10
  22#else
  23# define TIMEOUT_COUNT  (CONFIG_NET_RETRY_COUNT * 2)
  24#endif
  25/* Number of "loading" hashes per line (for checking the image size) */
  26#define HASHES_PER_LINE 65
  27
  28/*
  29 *      TFTP operations.
  30 */
  31#define TFTP_RRQ        1
  32#define TFTP_WRQ        2
  33#define TFTP_DATA       3
  34#define TFTP_ACK        4
  35#define TFTP_ERROR      5
  36#define TFTP_OACK       6
  37
  38static ulong TftpTimeoutMSecs = TIMEOUT;
  39static int TftpTimeoutCountMax = TIMEOUT_COUNT;
  40
  41/*
  42 * These globals govern the timeout behavior when attempting a connection to a
  43 * TFTP server. TftpRRQTimeoutMSecs specifies the number of milliseconds to
  44 * wait for the server to respond to initial connection. Second global,
  45 * TftpRRQTimeoutCountMax, gives the number of such connection retries.
  46 * TftpRRQTimeoutCountMax must be non-negative and TftpRRQTimeoutMSecs must be
  47 * positive. The globals are meant to be set (and restored) by code needing
  48 * non-standard timeout behavior when initiating a TFTP transfer.
  49 */
  50ulong TftpRRQTimeoutMSecs = TIMEOUT;
  51int TftpRRQTimeoutCountMax = TIMEOUT_COUNT;
  52
  53enum {
  54        TFTP_ERR_UNDEFINED           = 0,
  55        TFTP_ERR_FILE_NOT_FOUND      = 1,
  56        TFTP_ERR_ACCESS_DENIED       = 2,
  57        TFTP_ERR_DISK_FULL           = 3,
  58        TFTP_ERR_UNEXPECTED_OPCODE   = 4,
  59        TFTP_ERR_UNKNOWN_TRANSFER_ID  = 5,
  60        TFTP_ERR_FILE_ALREADY_EXISTS = 6,
  61};
  62
  63static IPaddr_t TftpRemoteIP;
  64/* The UDP port at their end */
  65static int      TftpRemotePort;
  66/* The UDP port at our end */
  67static int      TftpOurPort;
  68static int      TftpTimeoutCount;
  69/* packet sequence number */
  70static ulong    TftpBlock;
  71/* last packet sequence number received */
  72static ulong    TftpLastBlock;
  73/* count of sequence number wraparounds */
  74static ulong    TftpBlockWrap;
  75/* memory offset due to wrapping */
  76static ulong    TftpBlockWrapOffset;
  77static int      TftpState;
  78#ifdef CONFIG_TFTP_TSIZE
  79/* The file size reported by the server */
  80static int      TftpTsize;
  81/* The number of hashes we printed */
  82static short    TftpNumchars;
  83#endif
  84
  85#define STATE_SEND_RRQ  1
  86#define STATE_DATA      2
  87#define STATE_TOO_LARGE 3
  88#define STATE_BAD_MAGIC 4
  89#define STATE_OACK      5
  90#define STATE_RECV_WRQ  6
  91
  92/* default TFTP block size */
  93#define TFTP_BLOCK_SIZE         512
  94/* sequence number is 16 bit */
  95#define TFTP_SEQUENCE_SIZE      ((ulong)(1<<16))
  96
  97#define DEFAULT_NAME_LEN        (8 + 4 + 1)
  98static char default_filename[DEFAULT_NAME_LEN];
  99
 100#ifndef CONFIG_TFTP_FILE_NAME_MAX_LEN
 101#define MAX_LEN 128
 102#else
 103#define MAX_LEN CONFIG_TFTP_FILE_NAME_MAX_LEN
 104#endif
 105
 106static char tftp_filename[MAX_LEN];
 107
 108#ifdef CONFIG_SYS_DIRECT_FLASH_TFTP
 109extern flash_info_t flash_info[];
 110#endif
 111
 112/* 512 is poor choice for ethernet, MTU is typically 1500.
 113 * Minus eth.hdrs thats 1468.  Can get 2x better throughput with
 114 * almost-MTU block sizes.  At least try... fall back to 512 if need be.
 115 * (but those using CONFIG_IP_DEFRAG may want to set a larger block in cfg file)
 116 */
 117#ifdef CONFIG_TFTP_BLOCKSIZE
 118#define TFTP_MTU_BLOCKSIZE CONFIG_TFTP_BLOCKSIZE
 119#else
 120#define TFTP_MTU_BLOCKSIZE 1468
 121#endif
 122
 123static unsigned short TftpBlkSize = TFTP_BLOCK_SIZE;
 124static unsigned short TftpBlkSizeOption = TFTP_MTU_BLOCKSIZE;
 125
 126#ifdef CONFIG_MCAST_TFTP
 127#include <malloc.h>
 128#define MTFTP_BITMAPSIZE        0x1000
 129static unsigned *Bitmap;
 130static int PrevBitmapHole, Mapsize = MTFTP_BITMAPSIZE;
 131static uchar ProhibitMcast, MasterClient;
 132static uchar Multicast;
 133extern IPaddr_t Mcast_addr;
 134static int Mcast_port;
 135static ulong TftpEndingBlock; /* can get 'last' block before done..*/
 136
 137static void parse_multicast_oack(char *pkt, int len);
 138
 139static void
 140mcast_cleanup(void)
 141{
 142        if (Mcast_addr)
 143                eth_mcast_join(Mcast_addr, 0);
 144        if (Bitmap)
 145                free(Bitmap);
 146        Bitmap = NULL;
 147        Mcast_addr = Multicast = Mcast_port = 0;
 148        TftpEndingBlock = -1;
 149}
 150
 151#endif  /* CONFIG_MCAST_TFTP */
 152
 153static __inline__ void
 154store_block(unsigned block, uchar *src, unsigned len)
 155{
 156        ulong offset = block * TftpBlkSize + TftpBlockWrapOffset;
 157        ulong newsize = offset + len;
 158#ifdef CONFIG_SYS_DIRECT_FLASH_TFTP
 159        int i, rc = 0;
 160
 161        for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) {
 162                /* start address in flash? */
 163                if (flash_info[i].flash_id == FLASH_UNKNOWN)
 164                        continue;
 165                if (load_addr + offset >= flash_info[i].start[0]) {
 166                        rc = 1;
 167                        break;
 168                }
 169        }
 170
 171        if (rc) { /* Flash is destination for this packet */
 172                rc = flash_write((char *)src, (ulong)(load_addr+offset), len);
 173                if (rc) {
 174                        flash_perror(rc);
 175                        NetState = NETLOOP_FAIL;
 176                        return;
 177                }
 178        }
 179        else
 180#endif /* CONFIG_SYS_DIRECT_FLASH_TFTP */
 181        {
 182                (void)memcpy((void *)(load_addr + offset), src, len);
 183        }
 184#ifdef CONFIG_MCAST_TFTP
 185        if (Multicast)
 186                ext2_set_bit(block, Bitmap);
 187#endif
 188
 189        if (NetBootFileXferSize < newsize)
 190                NetBootFileXferSize = newsize;
 191}
 192
 193static void TftpSend(void);
 194static void TftpTimeout(void);
 195
 196/**********************************************************************/
 197
 198static void
 199TftpSend(void)
 200{
 201        volatile uchar *pkt;
 202        volatile uchar *xp;
 203        int             len = 0;
 204        volatile ushort *s;
 205
 206#ifdef CONFIG_MCAST_TFTP
 207        /* Multicast TFTP.. non-MasterClients do not ACK data. */
 208        if (Multicast
 209         && (TftpState == STATE_DATA)
 210         && (MasterClient == 0))
 211                return;
 212#endif
 213        /*
 214         *      We will always be sending some sort of packet, so
 215         *      cobble together the packet headers now.
 216         */
 217        pkt = NetTxPacket + NetEthHdrSize() + IP_HDR_SIZE;
 218
 219        switch (TftpState) {
 220
 221        case STATE_SEND_RRQ:
 222                xp = pkt;
 223                s = (ushort *)pkt;
 224                *s++ = htons(TFTP_RRQ);
 225                pkt = (uchar *)s;
 226                strcpy((char *)pkt, tftp_filename);
 227                pkt += strlen(tftp_filename) + 1;
 228                strcpy((char *)pkt, "octet");
 229                pkt += 5 /*strlen("octet")*/ + 1;
 230                strcpy((char *)pkt, "timeout");
 231                pkt += 7 /*strlen("timeout")*/ + 1;
 232                sprintf((char *)pkt, "%lu", TftpTimeoutMSecs / 1000);
 233                debug("send option \"timeout %s\"\n", (char *)pkt);
 234                pkt += strlen((char *)pkt) + 1;
 235#ifdef CONFIG_TFTP_TSIZE
 236                memcpy((char *)pkt, "tsize\0000\0", 8);
 237                pkt += 8;
 238#endif
 239                /* try for more effic. blk size */
 240                pkt += sprintf((char *)pkt, "blksize%c%d%c",
 241                                0, TftpBlkSizeOption, 0);
 242#ifdef CONFIG_MCAST_TFTP
 243                /* Check all preconditions before even trying the option */
 244                if (!ProhibitMcast
 245                 && (Bitmap = malloc(Mapsize))
 246                 && eth_get_dev()->mcast) {
 247                        free(Bitmap);
 248                        Bitmap = NULL;
 249                        pkt += sprintf((char *)pkt, "multicast%c%c", 0, 0);
 250                }
 251#endif /* CONFIG_MCAST_TFTP */
 252                len = pkt - xp;
 253                break;
 254
 255        case STATE_OACK:
 256#ifdef CONFIG_MCAST_TFTP
 257                /* My turn!  Start at where I need blocks I missed.*/
 258                if (Multicast)
 259                        TftpBlock = ext2_find_next_zero_bit(Bitmap,
 260                                                            (Mapsize*8), 0);
 261                /*..falling..*/
 262#endif
 263
 264        case STATE_RECV_WRQ:
 265        case STATE_DATA:
 266                xp = pkt;
 267                s = (ushort *)pkt;
 268                *s++ = htons(TFTP_ACK);
 269                *s++ = htons(TftpBlock);
 270                pkt = (uchar *)s;
 271                len = pkt - xp;
 272                break;
 273
 274        case STATE_TOO_LARGE:
 275                xp = pkt;
 276                s = (ushort *)pkt;
 277                *s++ = htons(TFTP_ERROR);
 278                *s++ = htons(3);
 279                pkt = (uchar *)s;
 280                strcpy((char *)pkt, "File too large");
 281                pkt += 14 /*strlen("File too large")*/ + 1;
 282                len = pkt - xp;
 283                break;
 284
 285        case STATE_BAD_MAGIC:
 286                xp = pkt;
 287                s = (ushort *)pkt;
 288                *s++ = htons(TFTP_ERROR);
 289                *s++ = htons(2);
 290                pkt = (uchar *)s;
 291                strcpy((char *)pkt, "File has bad magic");
 292                pkt += 18 /*strlen("File has bad magic")*/ + 1;
 293                len = pkt - xp;
 294                break;
 295        }
 296
 297        NetSendUDPPacket(NetServerEther, TftpRemoteIP, TftpRemotePort,
 298                         TftpOurPort, len);
 299}
 300
 301
 302static void
 303TftpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
 304            unsigned len)
 305{
 306        ushort proto;
 307        ushort *s;
 308        int i;
 309
 310        if (dest != TftpOurPort) {
 311#ifdef CONFIG_MCAST_TFTP
 312                if (Multicast
 313                 && (!Mcast_port || (dest != Mcast_port)))
 314#endif
 315                        return;
 316        }
 317        if (TftpState != STATE_SEND_RRQ && src != TftpRemotePort &&
 318            TftpState != STATE_RECV_WRQ)
 319                return;
 320
 321        if (len < 2)
 322                return;
 323        len -= 2;
 324        /* warning: don't use increment (++) in ntohs() macros!! */
 325        s = (ushort *)pkt;
 326        proto = *s++;
 327        pkt = (uchar *)s;
 328        switch (ntohs(proto)) {
 329
 330        case TFTP_RRQ:
 331        case TFTP_ACK:
 332                break;
 333        default:
 334                break;
 335
 336#ifdef CONFIG_CMD_TFTPSRV
 337        case TFTP_WRQ:
 338                debug("Got WRQ\n");
 339                TftpRemoteIP = sip;
 340                TftpRemotePort = src;
 341                TftpOurPort = 1024 + (get_timer(0) % 3072);
 342                TftpLastBlock = 0;
 343                TftpBlockWrap = 0;
 344                TftpBlockWrapOffset = 0;
 345                TftpSend(); /* Send ACK(0) */
 346                break;
 347#endif
 348
 349        case TFTP_OACK:
 350                debug("Got OACK: %s %s\n",
 351                        pkt,
 352                        pkt + strlen((char *)pkt) + 1);
 353                TftpState = STATE_OACK;
 354                TftpRemotePort = src;
 355                /*
 356                 * Check for 'blksize' option.
 357                 * Careful: "i" is signed, "len" is unsigned, thus
 358                 * something like "len-8" may give a *huge* number
 359                 */
 360                for (i = 0; i+8 < len; i++) {
 361                        if (strcmp((char *)pkt+i, "blksize") == 0) {
 362                                TftpBlkSize = (unsigned short)
 363                                        simple_strtoul((char *)pkt+i+8, NULL,
 364                                                       10);
 365                                debug("Blocksize ack: %s, %d\n",
 366                                        (char *)pkt+i+8, TftpBlkSize);
 367                        }
 368#ifdef CONFIG_TFTP_TSIZE
 369                        if (strcmp((char *)pkt+i, "tsize") == 0) {
 370                                TftpTsize = simple_strtoul((char *)pkt+i+6,
 371                                                           NULL, 10);
 372                                debug("size = %s, %d\n",
 373                                         (char *)pkt+i+6, TftpTsize);
 374                        }
 375#endif
 376                }
 377#ifdef CONFIG_MCAST_TFTP
 378                parse_multicast_oack((char *)pkt, len-1);
 379                if ((Multicast) && (!MasterClient))
 380                        TftpState = STATE_DATA; /* passive.. */
 381                else
 382#endif
 383                TftpSend(); /* Send ACK */
 384                break;
 385        case TFTP_DATA:
 386                if (len < 2)
 387                        return;
 388                len -= 2;
 389                TftpBlock = ntohs(*(ushort *)pkt);
 390
 391                /*
 392                 * RFC1350 specifies that the first data packet will
 393                 * have sequence number 1. If we receive a sequence
 394                 * number of 0 this means that there was a wrap
 395                 * around of the (16 bit) counter.
 396                 */
 397                if (TftpBlock == 0) {
 398                        TftpBlockWrap++;
 399                        TftpBlockWrapOffset +=
 400                                TftpBlkSize * TFTP_SEQUENCE_SIZE;
 401                        printf("\n\t %lu MB received\n\t ",
 402                                TftpBlockWrapOffset>>20);
 403                }
 404#ifdef CONFIG_TFTP_TSIZE
 405                else if (TftpTsize) {
 406                        while (TftpNumchars <
 407                               NetBootFileXferSize * 50 / TftpTsize) {
 408                                putc('#');
 409                                TftpNumchars++;
 410                        }
 411                }
 412#endif
 413                else {
 414                        if (((TftpBlock - 1) % 10) == 0)
 415                                putc('#');
 416                        else if ((TftpBlock % (10 * HASHES_PER_LINE)) == 0)
 417                                puts("\n\t ");
 418                }
 419
 420                if (TftpState == STATE_SEND_RRQ)
 421                        debug("Server did not acknowledge timeout option!\n");
 422
 423                if (TftpState == STATE_SEND_RRQ || TftpState == STATE_OACK ||
 424                    TftpState == STATE_RECV_WRQ) {
 425                        /* first block received */
 426                        TftpState = STATE_DATA;
 427                        TftpRemotePort = src;
 428                        TftpLastBlock = 0;
 429                        TftpBlockWrap = 0;
 430                        TftpBlockWrapOffset = 0;
 431
 432#ifdef CONFIG_MCAST_TFTP
 433                        if (Multicast) { /* start!=1 common if mcast */
 434                                TftpLastBlock = TftpBlock - 1;
 435                        } else
 436#endif
 437                        if (TftpBlock != 1) {   /* Assertion */
 438                                printf("\nTFTP error: "
 439                                       "First block is not block 1 (%ld)\n"
 440                                       "Starting again\n\n",
 441                                        TftpBlock);
 442                                NetStartAgain();
 443                                break;
 444                        }
 445                }
 446
 447                if (TftpBlock == TftpLastBlock) {
 448                        /*
 449                         *      Same block again; ignore it.
 450                         */
 451                        break;
 452                }
 453
 454                TftpLastBlock = TftpBlock;
 455                TftpTimeoutCountMax = TIMEOUT_COUNT;
 456                NetSetTimeout(TftpTimeoutMSecs, TftpTimeout);
 457
 458                store_block(TftpBlock - 1, pkt + 2, len);
 459
 460                /*
 461                 *      Acknowledge the block just received, which will prompt
 462                 *      the remote for the next one.
 463                 */
 464#ifdef CONFIG_MCAST_TFTP
 465                /* if I am the MasterClient, actively calculate what my next
 466                 * needed block is; else I'm passive; not ACKING
 467                 */
 468                if (Multicast) {
 469                        if (len < TftpBlkSize)  {
 470                                TftpEndingBlock = TftpBlock;
 471                        } else if (MasterClient) {
 472                                TftpBlock = PrevBitmapHole =
 473                                        ext2_find_next_zero_bit(
 474                                                Bitmap,
 475                                                (Mapsize*8),
 476                                                PrevBitmapHole);
 477                                if (TftpBlock > ((Mapsize*8) - 1)) {
 478                                        printf("tftpfile too big\n");
 479                                        /* try to double it and retry */
 480                                        Mapsize <<= 1;
 481                                        mcast_cleanup();
 482                                        NetStartAgain();
 483                                        return;
 484                                }
 485                                TftpLastBlock = TftpBlock;
 486                        }
 487                }
 488#endif
 489                TftpSend();
 490
 491#ifdef CONFIG_MCAST_TFTP
 492                if (Multicast) {
 493                        if (MasterClient && (TftpBlock >= TftpEndingBlock)) {
 494                                puts("\nMulticast tftp done\n");
 495                                mcast_cleanup();
 496                                NetState = NETLOOP_SUCCESS;
 497                        }
 498                }
 499                else
 500#endif
 501                if (len < TftpBlkSize) {
 502                        /*
 503                         *      We received the whole thing.  Try to
 504                         *      run it.
 505                         */
 506#ifdef CONFIG_TFTP_TSIZE
 507                        /* Print hash marks for the last packet received */
 508                        while (TftpTsize && TftpNumchars < 49) {
 509                                putc('#');
 510                                TftpNumchars++;
 511                        }
 512#endif
 513                        puts("\ndone\n");
 514                        NetState = NETLOOP_SUCCESS;
 515                }
 516                break;
 517
 518        case TFTP_ERROR:
 519                printf("\nTFTP error: '%s' (%d)\n",
 520                       pkt + 2, ntohs(*(ushort *)pkt));
 521
 522                switch (ntohs(*(ushort *)pkt)) {
 523                case TFTP_ERR_FILE_NOT_FOUND:
 524                case TFTP_ERR_ACCESS_DENIED:
 525                        puts("Not retrying...\n");
 526                        eth_halt();
 527                        NetState = NETLOOP_FAIL;
 528                        break;
 529                case TFTP_ERR_UNDEFINED:
 530                case TFTP_ERR_DISK_FULL:
 531                case TFTP_ERR_UNEXPECTED_OPCODE:
 532                case TFTP_ERR_UNKNOWN_TRANSFER_ID:
 533                case TFTP_ERR_FILE_ALREADY_EXISTS:
 534                default:
 535                        puts("Starting again\n\n");
 536#ifdef CONFIG_MCAST_TFTP
 537                        mcast_cleanup();
 538#endif
 539                        NetStartAgain();
 540                        break;
 541                }
 542                break;
 543        }
 544}
 545
 546
 547static void
 548TftpTimeout(void)
 549{
 550        if (++TftpTimeoutCount > TftpTimeoutCountMax) {
 551                puts("\nRetry count exceeded; starting again\n");
 552#ifdef CONFIG_MCAST_TFTP
 553                mcast_cleanup();
 554#endif
 555                NetStartAgain();
 556        } else {
 557                puts("T ");
 558                NetSetTimeout(TftpTimeoutMSecs, TftpTimeout);
 559                if (TftpState != STATE_RECV_WRQ)
 560                        TftpSend();
 561        }
 562}
 563
 564
 565void
 566TftpStart(void)
 567{
 568        char *ep;             /* Environment pointer */
 569
 570        /*
 571         * Allow the user to choose TFTP blocksize and timeout.
 572         * TFTP protocol has a minimal timeout of 1 second.
 573         */
 574        ep = getenv("tftpblocksize");
 575        if (ep != NULL)
 576                TftpBlkSizeOption = simple_strtol(ep, NULL, 10);
 577
 578        ep = getenv("tftptimeout");
 579        if (ep != NULL)
 580                TftpTimeoutMSecs = simple_strtol(ep, NULL, 10);
 581
 582        if (TftpTimeoutMSecs < 1000) {
 583                printf("TFTP timeout (%ld ms) too low, "
 584                        "set minimum = 1000 ms\n",
 585                        TftpTimeoutMSecs);
 586                TftpTimeoutMSecs = 1000;
 587        }
 588
 589        debug("TFTP blocksize = %i, timeout = %ld ms\n",
 590                TftpBlkSizeOption, TftpTimeoutMSecs);
 591
 592        TftpRemoteIP = NetServerIP;
 593        if (BootFile[0] == '\0') {
 594                sprintf(default_filename, "%02lX%02lX%02lX%02lX.img",
 595                        NetOurIP & 0xFF,
 596                        (NetOurIP >>  8) & 0xFF,
 597                        (NetOurIP >> 16) & 0xFF,
 598                        (NetOurIP >> 24) & 0xFF);
 599
 600                strncpy(tftp_filename, default_filename, MAX_LEN);
 601                tftp_filename[MAX_LEN-1] = 0;
 602
 603                printf("*** Warning: no boot file name; using '%s'\n",
 604                        tftp_filename);
 605        } else {
 606                char *p = strchr(BootFile, ':');
 607
 608                if (p == NULL) {
 609                        strncpy(tftp_filename, BootFile, MAX_LEN);
 610                        tftp_filename[MAX_LEN-1] = 0;
 611                } else {
 612                        TftpRemoteIP = string_to_ip(BootFile);
 613                        strncpy(tftp_filename, p + 1, MAX_LEN);
 614                        tftp_filename[MAX_LEN-1] = 0;
 615                }
 616        }
 617
 618#if defined(CONFIG_NET_MULTI)
 619        printf("Using %s device\n", eth_get_name());
 620#endif
 621        printf("TFTP from server %pI4"
 622                "; our IP address is %pI4", &TftpRemoteIP, &NetOurIP);
 623
 624        /* Check if we need to send across this subnet */
 625        if (NetOurGatewayIP && NetOurSubnetMask) {
 626                IPaddr_t OurNet = NetOurIP    & NetOurSubnetMask;
 627                IPaddr_t RemoteNet      = TftpRemoteIP & NetOurSubnetMask;
 628
 629                if (OurNet != RemoteNet)
 630                        printf("; sending through gateway %pI4",
 631                               &NetOurGatewayIP);
 632        }
 633        putc('\n');
 634
 635        printf("Filename '%s'.", tftp_filename);
 636
 637        if (NetBootFileSize) {
 638                printf(" Size is 0x%x Bytes = ", NetBootFileSize<<9);
 639                print_size(NetBootFileSize<<9, "");
 640        }
 641
 642        putc('\n');
 643
 644        printf("Load address: 0x%lx\n", load_addr);
 645
 646        puts("Loading: *\b");
 647
 648        TftpTimeoutCountMax = TftpRRQTimeoutCountMax;
 649
 650        NetSetTimeout(TftpTimeoutMSecs, TftpTimeout);
 651        NetSetHandler(TftpHandler);
 652
 653        TftpRemotePort = WELL_KNOWN_PORT;
 654        TftpTimeoutCount = 0;
 655        TftpState = STATE_SEND_RRQ;
 656        /* Use a pseudo-random port unless a specific port is set */
 657        TftpOurPort = 1024 + (get_timer(0) % 3072);
 658
 659#ifdef CONFIG_TFTP_PORT
 660        ep = getenv("tftpdstp");
 661        if (ep != NULL)
 662                TftpRemotePort = simple_strtol(ep, NULL, 10);
 663        ep = getenv("tftpsrcp");
 664        if (ep != NULL)
 665                TftpOurPort = simple_strtol(ep, NULL, 10);
 666#endif
 667        TftpBlock = 0;
 668
 669        /* zero out server ether in case the server ip has changed */
 670        memset(NetServerEther, 0, 6);
 671        /* Revert TftpBlkSize to dflt */
 672        TftpBlkSize = TFTP_BLOCK_SIZE;
 673#ifdef CONFIG_MCAST_TFTP
 674        mcast_cleanup();
 675#endif
 676#ifdef CONFIG_TFTP_TSIZE
 677        TftpTsize = 0;
 678        TftpNumchars = 0;
 679#endif
 680
 681        TftpSend();
 682}
 683
 684#ifdef CONFIG_CMD_TFTPSRV
 685void
 686TftpStartServer(void)
 687{
 688        tftp_filename[0] = 0;
 689
 690#if defined(CONFIG_NET_MULTI)
 691        printf("Using %s device\n", eth_get_name());
 692#endif
 693        printf("Listening for TFTP transfer on %pI4\n", &NetOurIP);
 694        printf("Load address: 0x%lx\n", load_addr);
 695
 696        puts("Loading: *\b");
 697
 698        TftpTimeoutCountMax = TIMEOUT_COUNT;
 699        TftpTimeoutCount = 0;
 700        TftpTimeoutMSecs = TIMEOUT;
 701        NetSetTimeout(TftpTimeoutMSecs, TftpTimeout);
 702
 703        /* Revert TftpBlkSize to dflt */
 704        TftpBlkSize = TFTP_BLOCK_SIZE;
 705        TftpBlock = 0;
 706        TftpOurPort = WELL_KNOWN_PORT;
 707
 708#ifdef CONFIG_TFTP_TSIZE
 709        TftpTsize = 0;
 710        TftpNumchars = 0;
 711#endif
 712
 713        TftpState = STATE_RECV_WRQ;
 714        NetSetHandler(TftpHandler);
 715}
 716#endif /* CONFIG_CMD_TFTPSRV */
 717
 718#ifdef CONFIG_MCAST_TFTP
 719/* Credits: atftp project.
 720 */
 721
 722/* pick up BcastAddr, Port, and whether I am [now] the master-client. *
 723 * Frame:
 724 *    +-------+-----------+---+-------~~-------+---+
 725 *    |  opc  | multicast | 0 | addr, port, mc | 0 |
 726 *    +-------+-----------+---+-------~~-------+---+
 727 * The multicast addr/port becomes what I listen to, and if 'mc' is '1' then
 728 * I am the new master-client so must send ACKs to DataBlocks.  If I am not
 729 * master-client, I'm a passive client, gathering what DataBlocks I may and
 730 * making note of which ones I got in my bitmask.
 731 * In theory, I never go from master->passive..
 732 * .. this comes in with pkt already pointing just past opc
 733 */
 734static void parse_multicast_oack(char *pkt, int len)
 735{
 736        int i;
 737        IPaddr_t addr;
 738        char *mc_adr, *port,  *mc;
 739
 740        mc_adr = port = mc = NULL;
 741        /* march along looking for 'multicast\0', which has to start at least
 742         * 14 bytes back from the end.
 743         */
 744        for (i = 0; i < len-14; i++)
 745                if (strcmp(pkt+i, "multicast") == 0)
 746                        break;
 747        if (i >= (len-14)) /* non-Multicast OACK, ign. */
 748                return;
 749
 750        i += 10; /* strlen multicast */
 751        mc_adr = pkt+i;
 752        for (; i < len; i++) {
 753                if (*(pkt+i) == ',') {
 754                        *(pkt+i) = '\0';
 755                        if (port) {
 756                                mc = pkt+i+1;
 757                                break;
 758                        } else {
 759                                port = pkt+i+1;
 760                        }
 761                }
 762        }
 763        if (!port || !mc_adr || !mc)
 764                return;
 765        if (Multicast && MasterClient) {
 766                printf("I got a OACK as master Client, WRONG!\n");
 767                return;
 768        }
 769        /* ..I now accept packets destined for this MCAST addr, port */
 770        if (!Multicast) {
 771                if (Bitmap) {
 772                        printf("Internal failure! no mcast.\n");
 773                        free(Bitmap);
 774                        Bitmap = NULL;
 775                        ProhibitMcast = 1;
 776                        return ;
 777                }
 778                /* I malloc instead of pre-declare; so that if the file ends
 779                 * up being too big for this bitmap I can retry
 780                 */
 781                Bitmap = malloc(Mapsize);
 782                if (!Bitmap) {
 783                        printf("No Bitmap, no multicast. Sorry.\n");
 784                        ProhibitMcast = 1;
 785                        return;
 786                }
 787                memset(Bitmap, 0, Mapsize);
 788                PrevBitmapHole = 0;
 789                Multicast = 1;
 790        }
 791        addr = string_to_ip(mc_adr);
 792        if (Mcast_addr != addr) {
 793                if (Mcast_addr)
 794                        eth_mcast_join(Mcast_addr, 0);
 795                Mcast_addr = addr;
 796                if (eth_mcast_join(Mcast_addr, 1)) {
 797                        printf("Fail to set mcast, revert to TFTP\n");
 798                        ProhibitMcast = 1;
 799                        mcast_cleanup();
 800                        NetStartAgain();
 801                }
 802        }
 803        MasterClient = (unsigned char)simple_strtoul((char *)mc, NULL, 10);
 804        Mcast_port = (unsigned short)simple_strtoul(port, NULL, 10);
 805        printf("Multicast: %s:%d [%d]\n", mc_adr, Mcast_port, MasterClient);
 806        return;
 807}
 808
 809#endif /* Multicast TFTP */
 810