⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 net_ipv4_tftp.c

📁 em86xx 完整启动程序,支持网络下载与串通下载
💻 C
字号:
/***************************************** Copyright (c) 2002-2004 Sigma Designs, Inc. All Rights Reserved Proprietary and Confidential *****************************************//* This file is part of the boot loader *//* * net_ipv4_tftp.c * * TFTP client  * Based on RFC 1350 "The TFTP Protocol (Revision 2)" * Based on RFC 1782 "TFTP Option Extension" * * Written by Ho Lee 11/20/2002 */#include "config.h"#include "util.h"#include "vsprintf.h"#include "uart.h"#include "timer.h"#include "net.h"#include "net_ipv4.h"static const char *blkstr = "blksize";/*     TFTP file transfer example (from RFC 1782)    Read Request      client                                           server      -------------------------------------------------------      |1|foofile|0|octet|0|blksize|0|1432|0|  -->               RRQ                                    <--  |6|blksize|0|1432|0|   OACK      |4|0|  -->                                                ACK                             <--  |3|1| 1432 octets of data |   DATA      |4|1|  -->                                                ACK                             <--  |3|2| 1432 octets of data |   DATA      |4|2|  -->                                                ACK                             <--  |3|3|<1432 octets of data |   DATA      |4|3|  -->                                                ACK*/int tftp_parsepacket(struct sk_buff *skb){    skb->tftp = (struct tftphdr *) ((char *) skb->udp + sizeof(struct udphdr));    skb->tftp->opcode = ntohs(skb->tftp->opcode);    switch (skb->tftp->opcode) {    case TFTPOP_DATA :        skb->tftp->u.data.block = ntohs(skb->tftp->u.data.block);        break;    case TFTPOP_ACK :        skb->tftp->u.ack.block = ntohs(skb->tftp->u.ack.block);        break;    case TFTPOP_ERROR :        skb->tftp->u.err.errcode = ntohs(skb->tftp->u.err.errcode);        break;    }    return 0;}void tftp_dump_packet(struct sk_buff *skb, int need_parsing){    uart_printf("TFTP : \n");}int ipv4_tftp(in_addr_t ipaddr, char *filename, unsigned int addr, unsigned int *datalen){    tftpip_t packet;    int len, nretry;    int nloop = 0, nloop2 = 0;    struct sk_buff *skb = NULL;    unsigned char *dataptr;    unsigned int iport = ipv4_alloc_port();    unsigned int blksize = TFTP_DEF_PACKET;    unsigned int last_block = 0;       dataptr = (unsigned char *) addr;    *datalen = 0;    // send RRQ    packet.tftp.opcode = htons(TFTPOP_RRQ);    len = sizeof packet.tftp.opcode;    len += sprintf((char *) packet.tftp.u.rrq, "%s%coctet%c%s%c%d",         filename, 0, 0, blkstr, 0, TFTP_MAX_PACKET);    len += 1;    for (nretry = 1; nretry <= MAX_TFTP_RETRIES; ++nretry) {        uart_printf("Getting (%s)...\n", filename);        udp_transmit(ipaddr, iport, IPPORT_TFTP, len, &packet, 0);        if ((skb = udp_receive(ipaddr, 0, iport, TIMEOUT)) != NULL)            break;        if (nretry == MAX_TFTP_RETRIES) {            uart_puts("Timeout. Connection failed.\n");            return TFTPRET_NETWORKERR;        } else {            uart_puts("Timeout. Retrying...\n");        }    }    while (skb) {        tftp_parsepacket(skb);        switch (skb->tftp->opcode) {        case TFTPOP_RRQ :         case TFTPOP_WRQ :         case TFTPOP_ACK :            // invalid op code for client            // just ignore them            break;        case TFTPOP_DATA :            // print progress            if ((nloop++ & 0x3f) == 0) {                if ((nloop2++ & 0x3f) == 0) {                    if (nloop2 == 1)                        uart_puts("Receiving");                    else                        uart_puts("\n            ");                }                uart_putc('.');            }            	    /* Save the last block# so if ack is lost we won't copy the               same packet more than once */            if (last_block != skb->tftp->u.data.block) {            	// Append to data buffer            	len = skb->udpdata_len - 4;            	memcpy(dataptr, skb->tftp->u.data.data, len);            	dataptr += len;            	*datalen += len;                last_block = skb->tftp->u.data.block;	    }            // reply ACK            packet.tftp.opcode = htons(TFTPOP_ACK);            packet.tftp.u.ack.block = htons(skb->tftp->u.data.block);            udp_transmit(ipaddr, iport, skb->udp->src, 4, &packet, 0);            if (len < blksize) {                uart_puts("\n");                //uart_printf("Received %d (0x%x) bytes\n", *datalen, *datalen);                return 0;            }            break;        case TFTPOP_ERROR :            switch (skb->tftp->u.err.errcode) {            case TFTPERR_FILENOTFOUND :                uart_puts("File not found\n");                return TFTPRET_FILENOTFOUND;            case TFTPERR_ACCESSDENIED :                uart_puts("Access denied\n");                return TFTPRET_ACCESSDENIED;            default :                uart_printf("TFTP error %d : %s\n",                     skb->tftp->u.err.errcode, skb->tftp->u.err.errmsg);                return TFTPRET_OTHER;            }            break;        case TFTPOP_OACK :            // reply with ACK	    if (strcmp(skb->tftp->u.oack.data, blkstr) == 0) {		blksize = atoi(&(skb->tftp->u.oack.data[strlen(blkstr) + 1]));		uart_printf("Block size set to %d.\n", blksize);	    }            packet.tftp.opcode = htons(TFTPOP_ACK);            packet.tftp.u.ack.block = 0;            udp_transmit(ipaddr, iport, skb->udp->src, 4, &packet, 0);            break;        }        skb_free(skb);        for (nretry = 1; nretry <= MAX_TFTP_RETRIES; ++nretry) {            if ((skb = udp_receive(ipaddr, 0, iport, TIMEOUT)) != NULL)                break;            if (nretry == MAX_TFTP_RETRIES) {                uart_puts("Timeout. Transfer failed.\n");                return TFTPRET_NETWORKERR;            }        }    }        return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -