您的位置:首页 > 编程语言 > PHP开发

uboot tftp code structure

2016-03-20 21:56 218 查看
TftpSend (void)

pkt = NetTxPacket + NetEthHdrSize() + IP_HDR_SIZE;

case STATE_RRQ:

xp = pkt;

s = (ushort *)pkt;

*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);

pkt += strlen((char *)pkt) + 1;

len = pkt - xp;

break;

NetSendUDPPacket(NetServerEther, NetServerIP, TftpServerPort, TftpOurPort, len);

这个函数向tftp server发送一个packet

在上面的case中,在这个case中,设置一个即将发送的读数据请求报文:TFTP动作、tftp传输的文件名、模式“octet”、选项0“timeout”,选项0的值5.

tftp传输的文件名,模式“octet”,选项0“timeout”,选项0的值5之间有‘\0'.

. TftpHandler()

这个函数时tftp client的接收到数据时处理函数,处理数据包、OACK包、error包等。

TftpHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len)

s = (ushort *)pkt;

proto = *s++; // 得到两字节的tftp动作编号

pkt = (uchar *)s;

switch (ntohs(proto)) {

case TFTP_RRQ:

case TFTP_WRQ:

case TFTP_ACK:

break;

default:

break;

case TFTP_OACK:

#ifdef ET_DEBUG

printf("Got OACK: %s %s\n", pkt, pkt+strlen(pkt)+1);

#endif

TftpState = STATE_OACK;

TftpServerPort = src;

TftpSend (); /* Send ACK */

break;

case TFTP_DATA: // 这个packet时tftp数据包

if (((TftpBlock - 1) % 10) == 0) { // TftpBlock是数据包的编号,每10个包才会输出一个#

putc ('#');

} else if ((TftpBlock % (10 * HASHES_PER_LINE)) == 0) { // 每650个包换行

puts ("\n\t ");

}

NetSetTimeout (TIMEOUT * CFG_HZ, TftpTimeout);

store_block (TftpBlock - 1, pkt + 2, len); // 将tftp数据包保存值存储器(flash或者RAM)

/*

* Acknoledge the block just received, which will prompt

* the server for the next one.

*/

TftpSend (); // 发送一个已接收到此数据包的ACK(格式:tftp动作编号ACK+这个数据包的编号)

.

void TftpStart (void)

这个函数主要做的事情如下:

1. 检查tftp传输的文件的文件名,如果是null,使用default文件名;

2. 设置tftp timeout处理函数;

NetSetTimeout (TIMEOUT * CFG_HZ, TftpTimeout);

3. 设置tftp client收到tftp包(有ACK包、OACK包、数据包等)后处理packet的函数

NetSetHandler (TftpHandler);

4. 设置tftp初始状态为读tftp server数据包请求STATE_RRQ;

TftpState = STATE_RRQ;

5. 发送这个读数据包请求的报文(格式:tftp动作编号+要读取的文件名+模式+timeout选项+timeout选项值)。

TftpSend ();

. TftpStart()的调用

tftpboot 0x1000000 u-boot

int do_tftpb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])

{

return netboot_common (TFTP, cmdtp, argc, argv);

}

U_BOOT_CMD( // 在cmd_net.c中

tftpboot,
3, 1, do_tftpb,

"tftpboot- boot image via network using TFTP protocol\n",

"[loadAddress] [bootfilename]\n"

);

netboot_common (proto_t proto, cmd_tbl_t *cmdtp, int argc, char *argv[])

switch (argc) {

case 3:
load_addr = simple_strtoul(argv[1], NULL, 16);

copy_filename (BootFile, argv[2], sizeof(BootFile));

if ((size = NetLoop(proto)) < 0)

return 1;

. NetReceive(volatile uchar * inpkt, int len)函数解析

NetReceive(volatile uchar * inpkt, int len) // inpkt是整个packet的内容,len是大小

x = ntohs(et->et_protlen); // 得到这个packet的长度或者协议

if (x < 1514) { // 这里的x应该是指packet的长度

/*

* Got a 802 packet. Check the other protocol field.

*/

x = ntohs(et->et_prot);

ip = (IP_t *)(inpkt + E802_HDR_SIZE);

len -= E802_HDR_SIZE;

} else if (x != PROT_VLAN) {
/* normal packet */ // 这里的x应该是指协议

ip = (IP_t *)(inpkt + ETHER_HDR_SIZE); // Ethernet header size,将ip指向这个packet header后面的数据部分。

len -= ETHER_HDR_SIZE; // packet的长度减去packet header的长度,结果len就是packet数据部分的长度。

} else {
/* VLAN packet */

switch(x)

case PROT_IP: // 使用ip协议

if (ip->ip_p == IPPROTO_ICMP) { // 现在的ip指向packet的Internet Protocol (IP) header

// 检查check sum

* IP header OK. Pass the packet to the current handler.

*/

// 处理packet的纯数据部分

(*packetHandler)((uchar *)ip +IP_HDR_SIZE,

ntohs(ip->udp_dst),

ntohs(ip->udp_src),

ntohs(ip->udp_len) - 8);

从上面可以总结这个packet的结构是这样的:

Ethernet header --- Internet Protocol (IP) header --- effective data

ETHER_HDR_SIZE IP_HDR_SIZE

基于TFTP协议的远程升级设计
http://blog.csdn.net/zhzht19861011/article/details/46403617
U-boot中TFTP解释及nfs命令的小bug
http://blog.chinaunix.net/uid-20672257-id-2899526.html
TFTP协议详解
http://linux.chinaunix.net/techdoc/net/2009/05/04/1109928.shtml
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: