windows上搭建嵌入式linux开发板的nfs和tftp服务
0、前言
在嵌入式开发中,经常会用到开发板的uboot通过网络下载服务器中的相关文件,或者使用nfs文件系统作为rootfs,通常的做法是在Ubuntu下安装相应的软件并启动该服务,如果本地没有Ubuntu系统,能否实现该功能呢。答案是肯定的,在windows下也可以搭建nfs和tftp服务器为开发板提供服务。
1、tftp服务器设置
Windows下TFTP的服务器软件有很多,这里推荐一个YaTFTPSvr,国人写的专为嵌入式系统开发而准备的TFTP服务器工具,官方地址如下https://sites.google.com/site/zhaojieding2/

这个工具为绿色软件,解压缩后直接运行TFTPSvr.exe即可。主界面默认有八个标签,每一个标签页可以添加一个目录作为TFTP的根目录,这样便于把多个目录映射到TFTP服务器的根目录,状态栏有提醒,正在69号端口侦听中。这里创建一个nfs目录,并把需要下载的文件比如u-boot.imx放置到改文件中。

在保证开发板和Windows系统在同一网段的前提下,就可以在开发板上使用tftp命令(tftp 80800000 u-boot.imx)从Windows系统中下载文件了,并且在服务器YaTFTPSvr上会有客户端访问的日志。
2、nfs服务器设置
Windows上的nfs服务器软件比较少,这里推荐一个haneWIN NFS Server,官方网址为https://www.hanewin.net/nfs-e.htm。

软件分为两种安装方式,其中service install是作为windows的服务来安装,这样就可以开机自启动。Application则作为绿色软件来使用,需要的时候手动启动软件才能提供nfs服务,并且软件有中文语言包。本人更喜欢绿色的Application方式,所以以此为例。

解压缩下载好的Application后,把中文语言配置文件解压到languages文件夹。
由于默认情况下,windows的防火墙会阻止nfs服务通过,所以需要把改软件添加到防火墙规则中,是的防火墙允许软件提供网络服务。这一点haneWIN NFS Server软件已经想到了,并且为我们准备了一个脚本文件,专门用来添加防火墙规则。

在firewall.bat右击,以管理员身份运行改脚本,即可添加规则到防火墙。

双击nfssrv-64.exe执行,就可以启动软件类,此时windows防火墙会报警,点击允许访问即可。

在菜单Edit中点击Preferences,弹出属性设置窗口,在Language标签中,选择Chinese.ini后确定,此时程序界面会有部分被汉化。

在属性窗口中的输出标签中,点击编辑输出文件,添加共享nfs目录后保存。

此时输出目录更新,在软件主窗口可以看到nfs共享的目录和属性。

把需要下载的文件拷贝到nfs目录中,在开发板上进入uboot,执行 “nfs 80800000 192.168.31.60:/nfs/zImage” 就可以下载相应文件了。

在编辑输出文件列表时,会使用一些参数,关于这些参数的详细描述以及该软件的其他参数配置,在软件的doc目录中的帮助文档里面有详细描述。haneWIN NFS Server是一个共享软件,不注册可以免费试用30天。
3、根文件系统设置
嵌入式linux系统的根文件系统也是可以通过nfs来挂在的。远程服务器编译好文件系统后,对于文件系统所在文件夹进行打包:
tar czvf rootfs.tar.gz rootfs

打包完成后,把压缩包下载到本地nfs目录中 。在windows中把压缩包解压到当前文件夹即可。

解压后根文件系统就准备好了。
在开发板的uboot中设置环境变量bootargs:
<pre class="prettyprint linenums prettyprinted" style="">
setenv bootcmd 'tftp 80800000 zImage; tftp 83000000 imx6ull-14x14-emmc-4.3-800x480-c.dtb; bootz 80800000 - 83000000'
setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs rw nfsroot=192.168.31.60:/d/Download/nfs/rootfs ip=192.168.31.251:192.168.31.60:192.168.31.1:255.255.255.0::eth0:off'
</pre>
重启开发板,系统就可以从nfs启动了。

启动后linux内核会寻找/sbin/init文件并执行,系统提示能够找到文件,但是不能执行,究其原因,毕竟我们不知在ext4分区中挂在的根文件系统,而是使用windows下的nfs挂载,所以会有一些小问题,比如这个问题就是对于linux下的软连接支持会有一些小问题,接下来逐一解决即可。
在window下的rootfs目录的sbin目录下,删除init文件,拷贝bin目录下的busybox文件到sbin目录下并重命名为init。
删除bin/sh文件,复制并粘贴busybox,重命名为sh。
删除lib/libm.so.6,复制并粘贴libm-2.19-2014.08-1-git.so,重命名为libm.so.6。
删除lib/libresolv.so.2,复制并粘贴libresolv-2.19-2014.08-1-git.so,重命名为libresolv.so.2。
删除/lib/libc.so.6,复制并粘贴libc-2.19-2014.08-1-git.so,重命名为libc.so.6
修改/etc/init.d/rcS,

在一些命令前面增加busybox,然后重新启动开发板。

此时就可以正常进入系统了。
登录系统后,可以使用busybox ls这样增加前缀的方式使用各种linux命令了。
但是这种方式还是很不方便,那么我们可以通过编写一个shell脚本,修正linux的软连接在windows下失效的问题。方法如下:
在windows中进入rootfs目录中的root子目录,新建文本文件fixcmd.sh,使用文本编辑器写入内容如下:
<pre class="prettyprint linenums prettyprinted" style="">
-
#!/bin/sh
-
# fix /bin command
-
dir=$(busybox ls /bin/)
-
for i in $dir
-
do
-
#busybox ln -sf /bin/busybox /sbin/$i
-
if [ $i != 'busybox' ]
-
then
-
busybox ln -sf /bin/busybox /bin/$i
-
fi
-
done
-
# fix /sbin command
-
dir=$(busybox ls /sbin/)
-
for i in $dir
-
do
-
busybox ln -sf /bin/busybox /sbin/$i
-
done
-
# fix /usr/bin command
-
dir=$(busybox ls /usr/bin/)
-
for i in $dir
-
do
-
busybox ln -sf /bin/busybox /usr/bin/$i
-
done
-
# fix /usr/sbin command
-
dir=$(busybox ls /usr/sbin/)
-
for i in $dir
-
do
-
busybox ln -sf /bin/busybox /usr/sbin/$i
-
done
</pre>
保存后进入开发板的串口终端,执行如下命令
<pre class="prettyprint linenums prettyprinted" style="">
cd /root
./fixcmd.sh
</pre>
等待几秒钟后修复完成,之后再终端中就可以直接受用linux各种命令了。

在haneWIN中需要设置上述两个选框,其中Set execute bit for all files保证文件系统中的可执行文件是可以运行的,不选中这个是不能被执行的。Map client root (UID 0) to root for all entries选择则可以保证系统是可写的,不选中系统只读。

在服务器设置页面中,必须选中Use Windows file ID as inode on NTFS volumes,否则linux内核无法通过nfs连接文件系统。
此外,Use NTFS reparse points for symbolic links也必须选中,这样才能使nfs下的软连接有效。
4、总结
在Windows下通过使用TFTP服务器软件和nfs服务器软件,可以让开发板在uboot阶段通过网络访问相应服务,与在本地使用虚拟机安装Ubuntu是一样的效果。TFPT的使用时很简单的,但是让开发板的linux内核挂载Windows下使用haneWIN共享的rootfs文件系统是难点,耗费了笔者两周时间,没有找到资料讲解如何设置,最后只能一点一点的实验,逐一解决问题,好在最终完美解决了。