现在的位置: 首页 > 综合 > 正文

在U-boot上搭建TFTP服务器

2013年10月07日 ⁄ 综合 ⁄ 共 6644字 ⁄ 字号 评论关闭

         实现这个的整体目的是为了以后实现远程更新u-boot kernel rootfs而设计的。目前已经完全在u-boot实现的TFTP服务器了。先把它贴出来。

说明:

Uboot3是没有改动的。

9UbootTftpServemini是移植好的。

u-boot版本为2009.11.

交叉工具链版本为:4.4.3

测试开发板:mini2440(这些修改都是板级无关的,其它板子应该也是可以的)

参考文档《BootLoader TFTP服务器功能的追加

一.添加命令tftpserver

         模仿tftpboot来添加,主要修改common/cmd_net.c和include/net.h。具体的改动如下:
          

--- Uboot3/common/cmd_net.c   2013-03-09 17:35:54.186849800 +0800
+++ 9UbootTftpServemini/common/cmd_net.c   2013-03-16 16:38:52.017695933 +0800
@@ -54,6 +54,17 @@
    "[loadAddress] [[hostIPaddr:]bootfilename]"
 );
 
+int do_tftpserver (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+   return netboot_common (TFTPSERVER , cmdtp, argc, argv);
+}
+
+U_BOOT_CMD(
+   tftpserver,   1,   1,   do_tftpserver,
+   "tftpserver-set  TFTP server,  wait client data.\n",
+   "[] []"
+);
+

 int do_rarpb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 {
    return netboot_common (RARP, cmdtp, argc, argv);
--- Uboot3/include/net.h   2013-03-09 17:35:55.110849761 +0800
+++ 9UbootTftpServemini/include/net.h   2013-03-16 17:02:29.281754689 +0800
@@ -356,7 +357,7 @@
 extern int      NetRestartWrap;      /* Tried all network devices   */
 #endif
 
-typedef enum { BOOTP, RARP, ARP, TFTP, DHCP, PING, DNS, NFS, CDP, NETCONS, SNTP } proto_t;
+typedef enum { BOOTP, RARP, ARP, TFTP, TFTPSERVER, DHCP, PING, DNS, NFS, CDP, NETCONS, SNTP } proto_t;
 
 /* from net/net.c */
 extern char   BootFile[128];         /* Boot File name      */
         
         这样就可以用这个命令了如下图所示:
         

二.网络层移植

         这次主要是移植的是net/net.c和include/net.h。添加仿照tftpboot的实现函数添加tftpserver函数TftpServerStart。具体的修改如下:

--- Uboot3/include/net.h   2013-03-09 17:35:55.110849761 +0800
+++ 9UbootTftpServemini/include/net.h   2013-03-16 17:02:29.281754689 +0800
@@ -329,6 +329,7 @@
 extern uchar      NetServerEther[6];   /* Boot server enet address   */
 extern IPaddr_t      NetOurIP;      /* Our    IP addr (0 = unknown)   */
 extern IPaddr_t      NetServerIP;      /* Server IP addr (0 = unknown)   */
+extern IPaddr_t      NetClientIP;      /* Server IP addr (0 = unknown)   */
 extern volatile uchar * NetTxPacket;      /* THE transmit packet      */
 extern volatile uchar * NetRxPackets[PKTBUFSRX];/* Receive packets      */
 extern volatile uchar * NetRxPacket;      /* Current receive packet   */
--- Uboot3/net/net.c   2013-03-09 17:35:54.282849796 +0800
+++ 9UbootTftpServemini/net/net.c   2013-03-17 12:26:15.460618862 +0800
@@ -80,6 +80,7 @@
 #include <net.h>
 #include "bootp.h"
 #include "tftp.h"
+#include "tftpserver.h"
 #include "rarp.h"
 #include "nfs.h"
 #ifdef CONFIG_STATUS_LED
@@ -138,6 +139,7 @@
          { 0, 0, 0, 0, 0, 0 };
 IPaddr_t   NetOurIP;      /* Our IP addr (0 = unknown)      */
 IPaddr_t   NetServerIP;      /* Server IP addr (0 = unknown)      */
+IPaddr_t   NetClientIP;      /* Server IP addr (0 = unknown)      */
 volatile uchar *NetRxPacket;      /* Current receive packet      */
 int      NetRxPacketLen;      /* Current rx packet length      */
 unsigned   NetIPID;      /* IP packet ID            */
@@ -279,6 +281,7 @@
 static void
 NetInitLoop(proto_t protocol)
 {
+   debug("NetInitLoop ... \n");
    static int env_changed_id = 0;
    bd_t *bd = gd->bd;
    int env_id = get_env_id ();
@@ -389,6 +392,12 @@
          TftpStart();
          break;
 
+      case TFTPSERVER:
+         puts("net.c/TFTPSERVER...\n");
+         /* always use ARP to get server ethernet address */
+         TftpServerStart();
+         break;
+

 #if defined(CONFIG_CMD_DHCP)
       case DHCP:
          BootpTry = 0;
@@ -1672,6 +1681,7 @@
       /*
        *   IP header OK.  Pass the packet to the current handler.
        */
+      NetClientIP   =   NetReadIP(&ip->ip_src);
       (*packetHandler)((uchar *)ip +IP_HDR_SIZE,
                   ntohs(ip->udp_dst),
                   ntohs(ip->udp_src),
@@ -1715,6 +1725,11 @@
    case NFS:
 #endif
    case NETCONS:
+   case TFTPSERVER:
+      if (NetOurIP == 0) {
+         puts ("*** ERROR: `ipaddr' not set\n");
+         return (1);
+      }

    case TFTP:
       if (NetServerIP == 0) {
          puts ("*** ERROR: `serverip' not set\n");

三.实现tftpserver处理函数

--- 9UbootTftpServemini/net/tftp.c    2013-03-17 14:59:43.660439608 +0800
+++ 9UbootTftpServemini/net/tftpserver.c    2013-03-17 15:36:20.575274671 +0800
@@ -7,7 +7,7 @@
 #include <common.h>
 #include <command.h>
 #include <net.h>
-#include "tftp.h"
+#include "tftpserver.h"
 #include "bootp.h"
 
 #if defined(CONFIG_CMD_NET)
@@ -44,8 +44,8 @@
  * positive. The globals are meant to be set (and restored) by code needing
  * non-standard timeout behavior when initiating a TFTP transfer.
  */
-ulong TftpRRQTimeoutMSecs = TIMEOUT;
-int TftpRRQTimeoutCountMax = TIMEOUT_COUNT;
+static ulong TftpRRQTimeoutMSecs = TIMEOUT;
+static TftpRRQTimeoutCountMax = TIMEOUT_COUNT;

 
 static IPaddr_t TftpServerIP;
 static int    TftpServerPort;        /* The UDP port at their end        */
@@ -66,6 +66,8 @@
 #define STATE_TOO_LARGE    3
 #define STATE_BAD_MAGIC    4
 #define STATE_OACK    5
+#define STATE_WAIT    6
+#define STATE_WRQ    7

 
 #define TFTP_BLOCK_SIZE        512            /* default TFTP block size    */
 #define TFTP_SEQUENCE_SIZE    ((ulong)(1<<16))    /* sequence number is 16 bit */
@@ -192,6 +194,15 @@
 
     switch (TftpState) {
 
+    case STATE_WRQ:
+        xp = pkt;
+        s = (ushort *)pkt;
+        *s++ = htons(TFTP_ACK);
+        *s++ = htons(TftpBlock);
+        pkt = (uchar *)s;
+        len = pkt - xp;
+        break;
+

     case STATE_RRQ:
         xp = pkt;
         s = (ushort *)pkt;
@@ -283,7 +294,7 @@
 #endif
         return;
     }
-    if (TftpState != STATE_RRQ && src != TftpServerPort) {
+    if (TftpState != STATE_WAIT && src != TftpServerPort) {
         return;
     }
 
@@ -299,6 +310,12 @@
 
     case TFTP_RRQ:
     case TFTP_WRQ:
+        NetServerIP        = NetClientIP;
+        TftpBlock        = 0;
+        TftpState        = STATE_WRQ;
+        TftpServerPort    = src;
+        TftpSend ();
+        break;

     case TFTP_ACK:
         break;
     default:
@@ -492,15 +509,13 @@
 #endif
         NetStartAgain ();
     } else {
-        puts ("T ");
         NetSetTimeout (TftpTimeoutMSecs, TftpTimeout);
-        TftpSend ();
     }
 }
 
 
 void
-TftpStart (void)
+TftpServerStart (void)
 {
     char *ep;             /* Environment pointer */
 
@@ -572,9 +587,9 @@
 
     TftpServerPort = WELL_KNOWN_PORT;
     TftpTimeoutCount = 0;
-    TftpState = STATE_RRQ;
+    TftpState = STATE_WAIT;
     /* Use a pseudo-random port unless a specific port is set */
-    TftpOurPort = 1024 + (get_timer(0) % 3072);
+    TftpOurPort = WELL_KNOWN_PORT;
 
 #ifdef CONFIG_TFTP_PORT
     if ((ep = getenv("tftpdstp")) != NULL) {
@@ -598,7 +613,6 @@
     TftpNumchars = 0;
 #endif
 
-    TftpSend ();
 }
 
 #ifdef CONFIG_MCAST_TFTP
--- Uboot3/net/tftp.h   2013-03-09 17:35:54.282849796 +0800
+++ 9UbootTftpServemini/net/tftpserver.h   2013-03-16 16:53:09.109731467 +0800
@@ -1,12 +1,14 @@
 /*
- *   LiMon - BOOTP/TFTP.
+ *   LiMon - BOOTP/TFTPSERVER.
+ *
+ *   2013 BY kangear
  *
  *   Copyright 1994, 1995, 2000 Neil Russell.
  *   (See License)
  */
 
-#ifndef __TFTP_H__
-#define __TFTP_H__
+#ifndef __TFTPSERVER_H__
+#define __TFTPSERVER_H__
 
 /**********************************************************************/
 /*
@@ -14,8 +16,8 @@
  */
 
 /* tftp.c */
-extern void   TftpStart (void);   /* Begin TFTP get */
+extern void   TftpServerStart (void);   /* Begin TFTPSERVER get */
 
 /**********************************************************************/
 
-#endif /* __TFTP_H__ */
+#endif /* __TFTPSERVER_H__ */
--- Uboot3/net/Makefile2013-03-09 17:35:54.282849796 +0800
+++ 9UbootTftpServemini/net/Makefile 2013-03-16 17:11:20.817776725 +0800
@@ -35,6 +35,7 @@
 COBJS-y += rarp.o
 COBJS-$(CONFIG_CMD_SNTP) += sntp.o
 COBJS-y += tftp.o
+COBJS-y += tftpserver.o
 
 COBJS := $(COBJS-y)
 SRCS := $(COBJS:.o=.c)
           测试一下:
关于上图的打印信息仍然是tftpboot时候的打印信息。可以根据实际情况更改。
启动一下看看:
可以看到是可以启动的。至此tftp服务器就算是移植成功了。

抱歉!评论已关闭.