zoukankan      html  css  js  c++  java
  • 让uboot的tftp支持上传功能

    转载:http://blog.chinaunix.net/uid-20737871-id-2124122.html

     

    uboot下的tftp下载功能是非常重要和常见的功能。但是偶尔有些特殊需求的人需要使用uboot的tftp具有上传功能。
    默认的uboot没有tftp上传功能,如果需要修改uboot代码。
    使用时键入第4个参数,则不同于3个参数的tftp下载功能。
    #tftp 50400000 xx.bin 10000
    TFTP to server 192.168.0.30; our IP address is 192.168.0.152
    Upload Filename 'xx.bin'.
    Upload from address: 0x50400000, 0.064 MB to be send ...
    Uploading: %#   [ Connected ]

             0.064 MB upload ok.
    这条命令将板子上0x50400000 开始,长度0x10000的数据上传到远程tftp服务器,命名为xx.bin

    这个修改在uboot1.3.4和2008.10版本上测试通过。
    1、修改common/cmd_net.c
    注释掉

        /*
        int do_tftpb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
        {
            return netboot_common (TFTP, cmdtp, argc, argv);
        }
        U_BOOT_CMD(
            tftpboot,    3,    1,    do_tftpb,
            "tftpboot- boot image via network using TFTP protocol
    ",
            "[loadAddress] [[hostIPaddr:]bootfilename]
    "
        );
        */

     

    可以看出默认uboot执行tftp命令其实调用的是tftpboot,uboot果然是看命名的前面几个字母而不是全名。例如print命令只需要键入pri。
    接着添加
        int do_tftp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
        {
            return netboot_common (TFTP, cmdtp, argc, argv);
        }
        U_BOOT_CMD(
            tftp,    4,    1,    do_tftp,
            "tftp	- download or upload image via network using TFTP protocol
    ",
            "[loadAddress] [bootfilename] <upload_size>
    "
        );

     

    然后修改netboot_common成如下代码
        static int
        netboot_common (proto_t proto, cmd_tbl_t *cmdtp, int argc, char *argv[])
        {
            extern ulong upload_addr;
            extern ulong upload_size;
            char *s;
            int rcode = 0;
            int size;
            /* pre-set load_addr */
            if ((s = getenv("loadaddr")) != NULL) {
                load_addr = simple_strtoul(s, NULL, 16);
            }
            switch (argc) {
            case 1:
                break;
            case 2:    /* only one arg - accept two forms:
                 * just load address, or just boot file name.
                 * The latter form must be written "filename" here.
                 */
                if (argv[1][0] == '"') {    /* just boot filename */
                    copy_filename (BootFile, argv[1], sizeof(BootFile));
                } else {            /* load address    */
                    load_addr = simple_strtoul(argv[1], NULL, 16);
                }
                break;
            case 3:    load_addr = simple_strtoul(argv[1], NULL, 16);
                copy_filename (BootFile, argv[2], sizeof(BootFile));
                upload_size = 0;
                
                break;
            
            case 4:
                upload_addr = simple_strtoul(argv[1], NULL, 16);
                upload_size = simple_strtoul(argv[3], NULL, 16);
                copy_filename (BootFile, argv[2], sizeof(BootFile));
                break;
            default: printf ("Usage:
    %s
    ", cmdtp->usage);
                show_boot_progress (-80);
                return 1;
            }
            show_boot_progress (80);
            if ((size = NetLoop(proto)) < 0) {
                show_boot_progress (-81);
                return 1;
            }
            show_boot_progress (81);
            /* NetLoop ok, update environment */
            netboot_update_env();
            /* done if no file was loaded (no errors though) */
            if (size == 0) {
                show_boot_progress (-82);
                return 0;
            }
            /* flush cache */
            flush_cache(load_addr, size);
            /* Loading ok, check if we should attempt an auto-start */
            if (((s = getenv("autostart")) != NULL) && (strcmp(s,"yes") == 0)) {
                char *local_args[2];
                local_args[0] = argv[0];
                local_args[1] = NULL;
                printf ("Automatic boot of image at addr 0x%08lX ...
    ",
                    load_addr);
                show_boot_progress (82);
                rcode = do_bootm (cmdtp, 0, 1, local_args);
            }
        #ifdef CONFIG_AUTOSCRIPT
            if (((s = getenv("autoscript")) != NULL) && (strcmp(s,"yes") == 0)) {
                printf ("Running autoscript at addr 0x%08lX", load_addr);
                s = getenv ("autoscript_uname");
                if (s)
                    printf (":%s ...
    ", s);
                else
                    puts (" ...
    ");
                show_boot_progress (83);
                rcode = autoscript (load_addr, s);
            }
        #endif
            if (rcode < 0)
                show_boot_progress (-83);
            else
                show_boot_progress (84);
            return rcode;
        }

     

    2、修改net/tftp.c 为
        /*
        * Copyright 1994, 1995, 2000 Neil Russell.
        * (See License)
        * Copyright 2000, 2001 DENX Software Engineering, Wolfgang Denk, wd@denx.de
        */
        #include <common.h>
        #include <command.h>
        #include <net.h>
        #include "tftp.h"
        #include "bootp.h"
        #undef ET_DEBUG
        #if defined(CONFIG_CMD_NET)
        #define WELL_KNOWN_PORT 69 /* Well known TFTP port # */
        #define TIMEOUT 1 /* Seconds to timeout for a lost pkt */
        #ifndef CONFIG_NET_RETRY_COUNT
        # define TIMEOUT_COUNT 10 /* # of timeouts before giving up */
        #else
        # define TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT * 2)
        #endif
        /* (for checking the image size) */
        #define TBLKS_PER_HASHES 64
        #define HASHES_PER_LINE 32 /* Number of "loading" hashes per line */
        /*
        * TFTP operations.
        */
        #define TFTP_RRQ 1
        #define TFTP_WRQ 2
        #define TFTP_DATA 3
        #define TFTP_ACK 4
        #define TFTP_ERROR 5
        #define TFTP_OACK 6
        #define STATE_OK 0
        #define STATE_ERROR 3
        #define STATE_WRQ 6
        #define STATE_ACK 7
        static IPaddr_t TftpServerIP;
        static int TftpServerPort; /* The UDP port at their end */
        static int TftpOurPort; /* The UDP port at our end */
        static int TftpTimeoutCount;
        static ulong TftpBlock; /* packet sequence number */
        static ulong TftpLastBlock; /* last packet sequence number received */
        static ulong TftpBlockWrap; /* count of sequence number wraparounds */
        static ulong TftpBlockWrapOffset; /* memory offset due to wrapping */
        static int TftpState;
        #define STATE_RRQ 1
        #define STATE_DATA 2
        #define STATE_TOO_LARGE 3
        #define STATE_BAD_MAGIC 4
        #define STATE_OACK 5
        #define TFTP_BLOCK_SIZE 512 /* default TFTP block size */
        #define TFTP_SEQUENCE_SIZE ((ulong)(1<<16)) /* sequence number is 16 bit */
        #define DEFAULT_NAME_LEN (8 + 4 + 1)
        static char default_filename[DEFAULT_NAME_LEN];
        #ifndef CONFIG_TFTP_FILE_NAME_MAX_LEN
        #define MAX_LEN 128
        #else
        #define MAX_LEN CONFIG_TFTP_FILE_NAME_MAX_LEN
        #endif
        static char tftp_filename[MAX_LEN];
        #ifdef CFG_DIRECT_FLASH_TFTP
        extern flash_info_t flash_info[];
        #endif
        ulong upload_addr = CFG_LOAD_ADDR; /* Default upLoad Address */
        ulong upload_size = 0;
        /* 512 is poor choice for ethernet, MTU is typically 1500.
        * Minus eth.hdrs thats 1468. Can get 2x better throughput with
        * almost-MTU block sizes. At least try... fall back to 512 if need be.
        */
        #define TFTP_MTU_BLOCKSIZE 1468
        static unsigned short TftpBlkSize=TFTP_BLOCK_SIZE;
        static unsigned short TftpBlkSizeOption=TFTP_MTU_BLOCKSIZE;
        #ifdef CONFIG_MCAST_TFTP
        #include <malloc.h>
        #define MTFTP_BITMAPSIZE 0x1000
        static unsigned *Bitmap;
        static int PrevBitmapHole,Mapsize=MTFTP_BITMAPSIZE;
        static uchar ProhibitMcast=0, MasterClient=0;
        static uchar Multicast=0;
        extern IPaddr_t Mcast_addr;
        static int Mcast_port;
        static ulong TftpEndingBlock; /* can get 'last' block before done..*/
        static void parse_multicast_oack(char *pkt,int len);
        static void
        mcast_cleanup(void)
        {
        if (Mcast_addr) eth_mcast_join(Mcast_addr, 0);
        if (Bitmap) free(Bitmap);
        Bitmap=NULL;
        Mcast_addr = Multicast = Mcast_port = 0;
        TftpEndingBlock = -1;
        }
        #endif /* CONFIG_MCAST_TFTP */
        static __inline__ void
        store_block (unsigned block, uchar * src, unsigned len)
        {
        ulong offset = block * TftpBlkSize + TftpBlockWrapOffset;
        ulong newsize = offset + len;
        #ifdef CFG_DIRECT_FLASH_TFTP
        int i, rc = 0;
        for (i=0; i<CFG_MAX_FLASH_BANKS; i++) {
        /* start address in flash? */
        if (flash_info[i].flash_id == FLASH_UNKNOWN)
        continue;
        if ((load_addr + offset >= flash_info[i].start[0]) && (load_addr + offset < flash_info[i].start[0] + flash_info[i].size)) {
        rc = 1;
        break;
        }
        }
        if (rc) { /* Flash is destination for this packet */
        rc = flash_write ((char *)src, (ulong)(load_addr+offset), len);
        if (rc) {
        flash_perror (rc);
        NetState = NETLOOP_FAIL;
        return;
        }
        }
        else
        #endif /* CFG_DIRECT_FLASH_TFTP */
        {
        (void)memcpy((void *)(load_addr + offset), src, len);
        }
        #ifdef CONFIG_MCAST_TFTP
        if (Multicast)
        ext2_set_bit(block, Bitmap);
        #endif
        if (NetBootFileXferSize < newsize)
        NetBootFileXferSize = newsize;
        }
        static void TftpSend (void);
        static void TftpTimeout (void);
        /**********************************************************************/
        static void
        TftpSend (void)
        {
        volatile uchar * pkt;
        volatile uchar * xp;
        int len = 0;
        int uplen=0;
        volatile ushort *s;
        #ifdef CONFIG_MCAST_TFTP
        /* Multicast TFTP.. non-MasterClients do not ACK data. */
        if (Multicast
        && (TftpState == STATE_DATA)
        && (MasterClient == 0))
        return;
        #endif
        /*
        * We will always be sending some sort of packet, so
        * cobble together the packet headers now.
        */
        pkt = NetTxPacket + NetEthHdrSize() + IP_HDR_SIZE;
        switch (TftpState) {
        case STATE_RRQ:
        case STATE_WRQ:
        xp = pkt;
        s = (ushort *)pkt;
        if(TftpState == STATE_WRQ)
        *s++ = htons(TFTP_WRQ);
        else *s++ = htons(TFTP_RRQ);
        pkt = (uchar *)s;
        strcpy ((char *)pkt, tftp_filename);
        pkt += strlen(tftp_filename) + 1;
        strcpy ((char *)pkt, "octet");
        pkt += 5 /*strlen("octet")*/ + 1;
        strcpy ((char *)pkt, "timeout");
        pkt += 7 /*strlen("timeout")*/ + 1;
        sprintf((char *)pkt, "%d", TIMEOUT);
        #ifdef ET_DEBUG
        printf("send option "timeout %s"
    ", (char *)pkt);
        #endif
        pkt += strlen((char *)pkt) + 1;
        /* try for more effic. blk size */
        if(TftpState == STATE_WRQ)
        pkt += sprintf((char *)pkt,"blksize%c%d%c",
        0,TftpBlkSizeOption,0);
        else
        pkt += sprintf((char *)pkt,"blksize%c%d%c",
        0,TftpBlkSizeOption,0);
        #ifdef CONFIG_MCAST_TFTP
        /* Check all preconditions before even trying the option */
        if (!ProhibitMcast
        && (Bitmap=malloc(Mapsize))
        && eth_get_dev()->mcast) {
        free(Bitmap);
        Bitmap=NULL;
        pkt += sprintf((char *)pkt,"multicast%c%c",0,0);
        }
        #endif /* CONFIG_MCAST_TFTP */
        len = pkt - xp;
        printf("%%");
        break;
        case STATE_OACK:
        #ifdef CONFIG_MCAST_TFTP
        /* My turn! Start at where I need blocks I missed.*/
        if (Multicast)
        TftpBlock=ext2_find_next_zero_bit(Bitmap,(Mapsize*8),0);
        /*..falling..*/
        #endif
        case STATE_DATA:
        xp = pkt;
        s = (ushort *)pkt;
        *s++ = htons(TFTP_ACK);
        *s++ = htons(TftpBlock);
        pkt = (uchar *)s;
        len = pkt - xp;
        break;
        case STATE_TOO_LARGE:
        xp = pkt;
        s = (ushort *)pkt;
        *s++ = htons(TFTP_ERROR);
        *s++ = htons(3);
        pkt = (uchar *)s;
        strcpy ((char *)pkt, "File too large");
        pkt += 14 /*strlen("File too large")*/ + 1;
        len = pkt - xp;
        break;
        case STATE_BAD_MAGIC:
        xp = pkt;
        s = (ushort *)pkt;
        *s++ = htons(TFTP_ERROR);
        *s++ = htons(2);
        pkt = (uchar *)s;
        strcpy ((char *)pkt, "File has bad magic");
        pkt += 18 /*strlen("File has bad magic")*/ + 1;
        len = pkt - xp;
        break;
        case STATE_ACK:
        xp = pkt;
        s = (ushort *)pkt;
        *s++ = htons(TFTP_DATA);
        *s++ = htons(TftpBlock+1);
        pkt = (uchar *)s;
        uplen = (upload_size-TftpBlock*TftpBlkSize);
        uplen = uplen > TftpBlkSize ? TftpBlkSize : uplen;
        memcpy((void*)pkt, (const char*)upload_addr + TftpBlock*TftpBlkSize , uplen);
        pkt += uplen;
        len = pkt - xp;
        break;
        default:
        return;
        }
        NetSendUDPPacket(NetServerEther, TftpServerIP, TftpServerPort, TftpOurPort, len);
        }
        static void tftp_show_transferd(int block, unsigned long wrap)
        {
        #define SHOW_TRANSFERD(tail) printf ("	[%2lu.%03lu MB]%s", ((block-1)* TftpBlkSize + wrap)>>20, 
        (((block-1) * TftpBlkSize + wrap)&0x0FFFFF)>>10, tail)
        if( ((block-1) & (TBLKS_PER_HASHES-1)) == 0)
        putc('#');
        if( ((block-1) & (TBLKS_PER_HASHES*HASHES_PER_LINE-1)) == 0) {
        if((block-1) ==0) {
        if(wrap==0) {
        puts("	[ Connected ]
    ");
        } else {
        SHOW_TRANSFERD(" [BlockCounter Reset]
    ");
        }
        } else {
        SHOW_TRANSFERD("
    ");
        }
        }
        #undef SHOW_TRANSFERD
        }
        static void
        TftpHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len)
        {
        ushort proto;
        ushort *s;
        int i;
        if (dest != TftpOurPort) {
        #ifdef CONFIG_MCAST_TFTP
        if (Multicast
        && (!Mcast_port || (dest != Mcast_port)))
        #endif
        return;
        }
        if ( !(TftpState==STATE_RRQ || TftpState==STATE_WRQ) && src != TftpServerPort) {
        return;
        }
        if (len < 2) {
        return;
        }
        len -= 2;
        /* warning: don't use increment (++) in ntohs() macros!! */
        s = (ushort *)pkt;
        proto = *s++;
        pkt = (uchar *)s;
        switch (ntohs(proto)) {
        case TFTP_RRQ:
        case TFTP_WRQ:
        break;
        case TFTP_ACK:
        TftpServerPort = src;
        TftpState=STATE_ACK;
        TftpBlock = ntohs(*(ushort *)pkt);
        if(TftpLastBlock == TftpBlock) {
        putc('%');
        } else {
        tftp_show_transferd(TftpBlock, TftpBlockWrapOffset);
        }
        TftpLastBlock = TftpBlock;
        NetSetTimeout (TIMEOUT * CFG_HZ, TftpTimeout);
        if(TftpBlkSize*TftpBlock> upload_size )
        {
        NetState = NETLOOP_SUCCESS;
        TftpState = STATE_OK;
        printf ("
    	 %lu.%03lu MB upload ok.
    ", (TftpBlockWrapOffset+upload_size)>>20,
        ((TftpBlockWrapOffset+upload_size)&0x0FFFFF)>>10);
        break;
        }
        TftpSend (); /* Send ACK */
        break;
        default:
        break;
        case TFTP_OACK:
        #ifdef ET_DEBUG
        printf("Got OACK: %s %s
    ", pkt, pkt+strlen(pkt)+1);
        #endif
        if(TftpState == STATE_WRQ)
        {
        TftpState = STATE_ACK;
        TftpBlock = 0;
        }
        else
        {
        TftpState = STATE_OACK;
        }
        TftpServerPort = src;
        /*
        * Check for 'blksize' option.
        * Careful: "i" is signed, "len" is unsigned, thus
        * something like "len-8" may give a *huge* number
        */
        for (i=0; i+8<len; i++) {
        if (strcmp ((char*)pkt+i,"blksize") == 0) {
        TftpBlkSize = (unsigned short)
        simple_strtoul((char*)pkt+i+8,NULL,10);
        #ifdef ET_DEBUG
        printf ("Blocksize ack: %s, %d
    ",
        (char*)pkt+i+8,TftpBlkSize);
        #endif
        break;
        }
        }
        #ifdef CONFIG_MCAST_TFTP
        parse_multicast_oack((char *)pkt,len-1);
        if ((Multicast) && (!MasterClient))
        TftpState = STATE_DATA; /* passive.. */
        else
        #endif
        TftpSend (); /* Send ACK */
        break;
        case TFTP_DATA:
        if (len < 2)
        return;
        len -= 2;
        TftpBlock = ntohs(*(ushort *)pkt);
        /*
        * RFC1350 specifies that the first data packet will
        * have sequence number 1. If we receive a sequence
        * number of 0 this means that there was a wrap
        * around of the (16 bit) counter.
        */
        if (TftpBlock == 0) {
        TftpBlockWrap++;
        TftpBlockWrapOffset += TftpBlkSize * TFTP_SEQUENCE_SIZE;
        printf ("
    	 %lu MB received
    	 ", TftpBlockWrapOffset>>20);
        } else {
        #if 0
        if (((TftpBlock - 1) % 10) == 0) {
        putc ('#');
        } else if ((TftpBlock % (10 * HASHES_PER_LINE)) == 0) {
        puts ("
    	 ");
        }
        #endif
        tftp_show_transferd(TftpBlock, TftpBlockWrapOffset);
        }
        #ifdef ET_DEBUG
        if (TftpState == STATE_RRQ) {
        puts ("Server did not acknowledge timeout option!
    ");
        }
        #endif
        if (TftpState == STATE_RRQ || TftpState == STATE_OACK) {
        /* first block received */
        TftpState = STATE_DATA;
        TftpServerPort = src;
        TftpLastBlock = 0;
        TftpBlockWrap = 0;
        TftpBlockWrapOffset = 0;
        #ifdef CONFIG_MCAST_TFTP
        if (Multicast) { /* start!=1 common if mcast */
        TftpLastBlock = TftpBlock - 1;
        } else
        #endif
        if (TftpBlock != 1) { /* Assertion */
        printf ("
    TFTP error: "
        "First block is not block 1 (%ld)
    "
        "Starting again
    
    ",
        TftpBlock);
        NetStartAgain ();
        break;
        }
        }
        if (TftpBlock == TftpLastBlock) {
        /*
        * Same block again; ignore it.
        */
        putc ('%');
        break;
        }
        TftpLastBlock = TftpBlock;
        NetSetTimeout (TIMEOUT * CFG_HZ, TftpTimeout);
        store_block (TftpBlock - 1, pkt + 2, len);
        /*
        * Acknoledge the block just received, which will prompt
        * the server for the next one.
        */
        #ifdef CONFIG_MCAST_TFTP
        /* if I am the MasterClient, actively calculate what my next
        * needed block is; else I'm passive; not ACKING
        */
        if (Multicast) {
        if (len < TftpBlkSize) {
        TftpEndingBlock = TftpBlock;
        } else if (MasterClient) {
        TftpBlock = PrevBitmapHole =
        ext2_find_next_zero_bit(
        Bitmap,
        (Mapsize*8),
        PrevBitmapHole);
        if (TftpBlock > ((Mapsize*8) - 1)) {
        printf ("tftpfile too big
    ");
        /* try to double it and retry */
        Mapsize<<=1;
        mcast_cleanup();
        NetStartAgain ();
        return;
        }
        TftpLastBlock = TftpBlock;
        }
        }
        #endif
        TftpSend ();
        #ifdef CONFIG_MCAST_TFTP
        if (Multicast) {
        if (MasterClient && (TftpBlock >= TftpEndingBlock)) {
        puts ("
    Multicast tftp done
    ");
        mcast_cleanup();
        NetState = NETLOOP_SUCCESS;
        }
        }
        else
        #endif
        if (len < TftpBlkSize) {
        /*
        * We received the whole thing. Try to
        * run it.
        */
        printf ("
    	 %lu.%03lu MB download ok.
    ", ((TftpBlock-1)* TftpBlkSize + TftpBlockWrapOffset)>>20,
        (((TftpBlock-1) * TftpBlkSize + TftpBlockWrapOffset)&0x0FFFFF)>>10);
        puts ("
    done
    ");
        NetState = NETLOOP_SUCCESS;
        }
        break;
        case TFTP_ERROR:
        printf ("
    TFTP error: '%s' (%d)
    ",
        pkt + 2, ntohs(*(ushort *)pkt));
        puts ("Starting again
    
    ");
        #ifdef CONFIG_MCAST_TFTP
        mcast_cleanup();
        #endif
        NetStartAgain ();
        break;
        }
        }
        static void
        TftpTimeout (void)
        {
        if (++TftpTimeoutCount > TIMEOUT_COUNT) {
        puts ("
    Retry count exceeded; starting again
    ");
        #ifdef CONFIG_MCAST_TFTP
        mcast_cleanup();
        #endif
        NetStartAgain ();
        } else {
        puts ("T ");
        NetSetTimeout (TIMEOUT * CFG_HZ, TftpTimeout);
        TftpSend ();
        }
        }
        void
        TftpStart (void)
        {
        #ifdef CONFIG_TFTP_PORT
        char *ep; /* Environment pointer */
        #endif
        if(upload_size)
        TftpState = STATE_WRQ;
        else TftpState = STATE_RRQ;
        TftpServerIP = NetServerIP;
        if (BootFile[0] == '') {
        sprintf(default_filename, "%02lX%02lX%02lX%02lX.img",
        NetOurIP & 0xFF,
        (NetOurIP >> 8) & 0xFF,
        (NetOurIP >> 16) & 0xFF,
        (NetOurIP >> 24) & 0xFF );
        strncpy(tftp_filename, default_filename, MAX_LEN);
        tftp_filename[MAX_LEN-1] = 0;
        printf ("*** Warning: no boot file name; using '%s'
    ",
        tftp_filename);
        } else {
        char *p = strchr (BootFile, ':');
        if (p == NULL) {
        strncpy(tftp_filename, BootFile, MAX_LEN);
        tftp_filename[MAX_LEN-1] = 0;
        } else {
        *p++ = '';
        TftpServerIP = string_to_ip (BootFile);
        strncpy(tftp_filename, p, MAX_LEN);
        tftp_filename[MAX_LEN-1] = 0;
        }
        }
        #if defined(CONFIG_NET_MULTI)
        printf ("Using %s device
    ", eth_get_name());
        #endif
        if( TftpState == STATE_WRQ)
        {
        puts ("TFTP to server "); print_IPaddr (NetServerIP);
        }
        else
        {
        puts ("TFTP from server "); print_IPaddr (TftpServerIP);
        }
        puts ("; our IP address is "); print_IPaddr (NetOurIP);
        /* Check if we need to send across this subnet */
        if (NetOurGatewayIP && NetOurSubnetMask) {
        IPaddr_t OurNet = NetOurIP & NetOurSubnetMask;
        IPaddr_t ServerNet = TftpServerIP & NetOurSubnetMask;
        if (OurNet != ServerNet) {
        puts ("; sending through gateway ");
        print_IPaddr (NetOurGatewayIP) ;
        }
        }
        putc ('
    ');
        if( TftpState == STATE_WRQ)
        printf ("Upload Filename '%s'.", tftp_filename);
        else printf ("Download Filename '%s'.", tftp_filename);
        if (NetBootFileSize) {
        printf (" Size is 0x%x Bytes = ", NetBootFileSize<<9);
        print_size (NetBootFileSize<<9, "");
        }
        putc ('
    ');
        if( TftpState == STATE_WRQ)
        {
        printf ("Upload from address: 0x%lx, ", upload_addr);
        printf ("%lu.%03lu MB to be send ...
    ", upload_size>>20, (upload_size&0x0FFFFF)>>10);
        printf ("Uploading: *");
        }
        else
        {
        printf ("Download to address: 0x%lx
    ", load_addr);
        printf ("Downloading: *");
        }
        NetSetTimeout (TIMEOUT * CFG_HZ, TftpTimeout);
        NetSetHandler (TftpHandler);
        TftpServerPort = WELL_KNOWN_PORT;
        TftpTimeoutCount = 0;
        /* Use a pseudo-random port unless a specific port is set */
        TftpOurPort = 1024 + (get_timer(0) % 3072);
        #ifdef CONFIG_TFTP_PORT
        if ((ep = getenv("tftpdstp")) != NULL) {
        TftpServerPort = simple_strtol(ep, NULL, 10);
        }
        if ((ep = getenv("tftpsrcp")) != NULL) {
        TftpOurPort= simple_strtol(ep, NULL, 10);
        }
        #endif
        TftpBlock = 0;
        TftpLastBlock = 0;
        TftpBlockWrap = 0;
        TftpBlockWrapOffset = 0;
        /* zero out server ether in case the server ip has changed */
        memset(NetServerEther, 0, 6);
        /* Revert TftpBlkSize to dflt */
        TftpBlkSize = TFTP_BLOCK_SIZE;
        #ifdef CONFIG_MCAST_TFTP
        mcast_cleanup();
        #endif
        TftpSend ();
        }
        #ifdef CONFIG_MCAST_TFTP
        /* Credits: atftp project.
        */
        /* pick up BcastAddr, Port, and whether I am [now] the master-client. *
        * Frame:
        * +-------+-----------+---+-------~~-------+---+
        * | opc | multicast | 0 | addr, port, mc | 0 |
        * +-------+-----------+---+-------~~-------+---+
        * The multicast addr/port becomes what I listen to, and if 'mc' is '1' then
        * I am the new master-client so must send ACKs to DataBlocks. If I am not
        * master-client, I'm a passive client, gathering what DataBlocks I may and
        * making note of which ones I got in my bitmask.
        * In theory, I never go from master->passive..
        * .. this comes in with pkt already pointing just past opc
        */
        static void parse_multicast_oack(char *pkt, int len)
        {
        int i;
        IPaddr_t addr;
        char *mc_adr, *port, *mc;
        mc_adr=port=mc=NULL;
        /* march along looking for 'multicast', which has to start at least
        * 14 bytes back from the end.
        */
        for (i=0;i<len-14;i++)
        if (strcmp (pkt+i,"multicast") == 0)
        break;
        if (i >= (len-14)) /* non-Multicast OACK, ign. */
        return;
        i+=10; /* strlen multicast */
        mc_adr = pkt+i;
        for (;i<len;i++) {
        if (*(pkt+i) == ',') {
        *(pkt+i) = '';
        if (port) {
        mc = pkt+i+1;
        break;
        } else {
        port = pkt+i+1;
        }
        }
        }
        if (!port || !mc_adr || !mc ) return;
        if (Multicast && MasterClient) {
        printf ("I got a OACK as master Client, WRONG!
    ");
        return;
        }
        /* ..I now accept packets destined for this MCAST addr, port */
        if (!Multicast) {
        if (Bitmap) {
        printf ("Internal failure! no mcast.
    ");
        free(Bitmap);
        Bitmap=NULL;
        ProhibitMcast=1;
        return ;
        }
        /* I malloc instead of pre-declare; so that if the file ends
        * up being too big for this bitmap I can retry
        */
        if (!(Bitmap = malloc (Mapsize))) {
        printf ("No Bitmap, no multicast. Sorry.
    ");
        ProhibitMcast=1;
        return;
        }
        memset (Bitmap,0,Mapsize);
        PrevBitmapHole = 0;
        Multicast = 1;
        }
        addr = string_to_ip(mc_adr);
        if (Mcast_addr != addr) {
        if (Mcast_addr)
        eth_mcast_join(Mcast_addr, 0);
        if (eth_mcast_join(Mcast_addr=addr, 1)) {
        printf ("Fail to set mcast, revert to TFTP
    ");
        ProhibitMcast=1;
        mcast_cleanup();
        NetStartAgain();
        }
        }
        MasterClient = (unsigned char)simple_strtoul((char *)mc,NULL,10);
        Mcast_port = (unsigned short)simple_strtoul(port,NULL,10);
        printf ("Multicast: %s:%d [%d]
    ", mc_adr, Mcast_port, MasterClient);
        return;
        }
        #endif /* Multicast TFTP */
        #endif

     

  • 相关阅读:
    面试总结进程、线程与多线程
    精妙算法收集一道有趣的腾讯笔试加分题
    反汇编分析寄存器状态
    远程桌面快捷键
    Js中 关于top、clientTop、scrollTop、offsetTop的用法
    JavaScript获取CSS属性
    oracle开启日志归档 (成功)
    eclipse插件开发帮助文档地址
    alter system修改oracle参数
    oracle分析统计表
  • 原文地址:https://www.cnblogs.com/pengdonglin137/p/3757676.html
Copyright © 2011-2022 走看看