Web failsafe httpd 移植到uboot_mt7620的过程

以 u-boot_sources_for_tp-link_AR9331_by_pepe2k 为蓝本。

将net目录下的Makefile、httpd.c 和 uip-0.9目录复制覆盖到mt7620目录,Makefile可以直接覆盖。

最关键的文件是net.c,需要对照蓝本文件好好进行修改,大致修改的地方有这些:

net.c的前部,加入必须的包含文件和相关变量定义,

#include "httpd.h"
#include "uip-0.9/uipopt.h"
#include "uip-0.9/uip.h"
#include "uip-0.9/uip_arp.h"

#if (CONFIG_COMMANDS & CFG_CMD_NET)

DECLARE_GLOBAL_DATA_PTR;

#define ARP_TIMEOUT			5		/* Seconds before trying ARP again */

#ifndef	CONFIG_NET_RETRY_COUNT
# define ARP_TIMEOUT_COUNT	5		/* # of timeouts before giving up  */
#else
# define ARP_TIMEOUT_COUNT  (CONFIG_NET_RETRY_COUNT)
#endif

unsigned char *webfailsafe_data_pointer = NULL;
int	webfailsafe_is_running = 0;
int	webfailsafe_ready_for_upgrade = 0;
int	webfailsafe_upgrade_type = WEBFAILSAFE_UPGRADE_TYPE_FIRMWARE;

在文件的末尾,加入最关键的函数:int NetLoopHttpd(void) 

此函数不能完全照搬蓝本代码,因为NetLoop初始化网卡的部分不一样,所以,前半部分的代码可以从NetLoop部分复制过来。

但是出现一个奇怪的问题,正常的网卡初始化,应该打印出如下内容:

NetTxPacket = 0x83FE5300 

 KSEG1ADDR(NetTxPacket) = 0xA3FE5300 

 NetLoop,call eth_halt ! 

 NetLoop,call eth_init ! 
Trying Eth0 (10/100-M)

 Waitting for RX_DMA_BUSY status Start... done


 ETH_STATE_ACTIVE!! 

但是我修改之后的NetLoopHttpd,出现的内容是:

 NetTxPacket = 0x00400000 

 Packet Buffer is empty ! 

直接调用NetLoop,发现也是同样的问题,看来调用该方法之前,应该有个初始化的过程。

通过mt7620原有的tftp过程来分析,仔细分析cmd_net.c,发现少掉了一个非常关键的初始化函数!

eth_initialize(gd->bd);

加入之后,终于看到了变化的信息:

 NetTxPacket = 0x83FE4F60 

 KSEG1ADDR(NetTxPacket) = 0xA3FE4F60 

 NetLoop,call eth_halt ! 

 NetLoop,call eth_init ! 
Trying Eth0 (10/100-M)

 Waitting for RX_DMA_BUSY status Start... done


 ETH_STATE_ACTIVE!! 
HTTP server is starting at IP: 1.1.168.192
HTTP server is ready!

等等!怎么IP地址是倒过来的?地址192.168.1.1不能联通!!!通过计算机运行arp -a,发现192.168.1.1不在列表

C:\Users\Administrator>arp -a

接口: 192.168.1.100 --- 0xb
  Internet 地址         物理地址              类型
  192.168.1.255         ff-ff-ff-ff-ff-ff     静态
  224.0.0.22            01-00-5e-00-00-16     静态
  224.0.0.251           01-00-5e-00-00-fb     静态
  224.0.0.252           01-00-5e-00-00-fc     静态
  239.192.152.143       01-00-5e-40-98-8f     静态

这说明ARP的相关操作没有成功!可能是字节序的处理上有些问题。

现在要从哪里入手呢?在关键的代码上加上输出语句,用来确定代码的执行顺序。

在net.c文件中,NetReceive 调用了 NetReceiveHttpd

	if(webfailsafe_is_running) {
		NetReceiveHttpd(inpkt, len);
		return;
	}

NetReceiveHttpd代码如下:

void NetReceiveHttpd(volatile uchar * inpkt, int len) {

	memcpy(uip_buf, (const void *) inpkt, len);
	uip_len = len;

#ifdef ET_DEBUG
	printf("NetReceiveHttpd buf->type = %04X\n", ntohs(BUF->type));	
#endif

	if (BUF->type == htons(UIP_ETHTYPE_IP)) {

#ifdef ET_DEBUG
		printf("buf type is UIP_ETHTYPE_IP\n");	
#endif
		
		uip_arp_ipin();
		uip_input();
		if (uip_len > 0) {
			uip_arp_out();
			NetSendHttpd();
		}
	} else if (BUF->type == htons(UIP_ETHTYPE_ARP)) {

#ifdef ET_DEBUG
		printf("buf type is UIP_ETHTYPE_ARP\n");	
#endif
		uip_arp_arpin();
		if (uip_len > 0) {
			NetSendHttpd();
		}
	}
}

通过加入的诊断输出语句,发现路由器收到了UIP_ETHTYPE_IP和UIP_ETHTYPE_ARP包,那就很有可能是处理的时候,出了什么问题。

继续分析uip_arp_ipin()函数(位于uip-0.9目录下的uip_arp.c文件中):

void uip_arp_ipin(void)
{
  uip_len -= sizeof(struct uip_eth_hdr);


	printf("uip_host_addr = %04X-%04X\n", uip_hostaddr[0],uip_hostaddr[1]);
	printf("uip_arp_netmask = %04X-%04X\n", uip_arp_netmask[0],uip_arp_netmask[1]);
	printf("ipbuf scripaddr = %04X-%04X\n", IPBUF->srcipaddr[0],IPBUF->srcipaddr[1]);
	printf("IPBUF->ethhdr.src = %08X\n", IPBUF->ethhdr.src);
	
  /* Only insert/update an entry if the source IP address of the
     incoming IP packet comes from a host on the local network. */
  if((IPBUF->srcipaddr[0] & uip_arp_netmask[0]) !=
     (uip_hostaddr[0] & uip_arp_netmask[0])) {
    return;
  }
  if((IPBUF->srcipaddr[1] & uip_arp_netmask[1]) !=
     (uip_hostaddr[1] & uip_arp_netmask[1])) {
    return;
  }
  uip_arp_update(IPBUF->srcipaddr, &(IPBUF->ethhdr.src));
  
  return;
}

加入了诊断输出的代码,在TTL console下观察,果然发现了问题!

buf type is UIP_ETHTYPE_IP
uip_host_addr = C0A8-0101
uip_arp_netmask = FFFF-FF00
ipbuf scripaddr = A8C0-6401
IPBUF->ethhdr.src = D3B65A70

注意:uip_host_addr是我们路由器的IP地址:192.168.1.1,正确。

但是,从网络上来的ip显然存在字节序问题,这应该是网络字节序,而代码当中却没有进行转换!

要修改的地方很多,而蓝本代码应该在它自己的目标机上运行正确,难道在某个地方有个统一转换的?

功夫不负有心人!在 include\asm\byteorder.h 中,有这样的定义:

#if defined (__MIPSEB__)
#  include <linux/byteorder/big_endian.h>
#elif defined (__MIPSEL__)
#  include <linux/byteorder/little_endian.h>
#else
#  error "MIPS, but neither __MIPSEB__, nor __MIPSEL__???"
#endif

猛然回想起来,以前编译AR系列的时候,用的都是-EB参数!而现在编译mt7620,用的是mipsel编译!!

找到网上这个地址:http://www.gaisler.com/doc/net/uip-0.9/doc/html/a00093.html

Detailed Description

The CPU architecture configuration is where the endianess of the CPU on which uIP is to be run is specified. Most CPUs today are little endian, and the most notable exception are the Motorolas which are big endian. The BYTE_ORDER macro should be changed to reflect the CPU architecture on which uIP is to be run.

Defines

#define 	BYTE_ORDER
 	The byte order of the CPU architecture on which uIP is to be run. 

Define Documentation

#define BYTE_ORDER
 	
The byte order of the CPU architecture on which uIP is to be run.

This option can be either BIG_ENDIAN (Motorola byte order) or LITTLE_ENDIAN (Intel byte order).

原来uip的字节序是可以自定义的!修改为LITTLE_ENDIAN之后,重新编译,也没有用!

看来还要仔细的思考一番。对比TTL console的诊断输出

ipbuf scripaddr = A8C0-6401

这是网络字节序,故思考所有的host端内容,要转成网络序才行。

思索再三,觉得在NetLoopHttpd中,几处设置网络地址参数的地方有点问题,遂进行了如下修改:

	// 修改1,网络字节序要先转成host字节序
	IPaddr_t x = ntohl(bd->bi_ip_addr);

	// start server...
	char tmp[22];
	ip_to_string(bd->bi_ip_addr,tmp);
	printf("HTTP server is starting at IP : %s\n",tmp);

	//TftpStart();
	HttpdStart();

	// set local host ip address,修改2,所有的host字节序,要转成网络字节序,下同
	ip[0] = htons(((x & 0xFFFF0000) >> 16));
	ip[1] = htons((x & 0x0000FFFF));

	uip_sethostaddr(ip);

	// set network mask (255.255.255.0 -> local network)
	ip[0] = htons(0xFFFF); //((0xFFFFFF00 & 0xFFFF0000) >> 16);
	ip[1] = htons(0xFF00); //(0xFFFFFF00 & 0x0000FFFF);

	uip_setnetmask(ip);

	// should we also set default router ip address?
	ip[0] = 0xFFFF;
	ip[1] = 0xFFFF;
	uip_setdraddr(ip);

修改完后,编译烧录,OK!终于在arp表中看到了久违的内容!

C:\Users\Administrator>arp -a

接口: 192.168.1.100 --- 0xb
  Internet 地址         物理地址              类型
  192.168.1.1           00-00-aa-bb-cc-dd     动态
  192.168.1.255         ff-ff-ff-ff-ff-ff     静态
  224.0.0.22            01-00-5e-00-00-16     静态
  224.0.0.251           01-00-5e-00-00-fb     静态
  224.0.0.252           01-00-5e-00-00-fc     静态
  239.192.152.143       01-00-5e-40-98-8f     静态

同时,浏览器中也能成功显示192.168.1.1的固件升级内容了!

至此,移植工作已经取得了阶段性的胜利!

整个过程,大概耗费了2天的时间。多数时间在这个网络与host字节序上转圈!




你可能感兴趣的:(Web failsafe httpd 移植到uboot_mt7620的过程)