一沙一世界 一树一菩提
分类: LINUX
2015-07-13 13:02:07
R8610移植linux-3.0.4,新文件系统
第一阶段,移植linux-3.0.4
最近一直在做r8610平台上的移植和开发工作。
公司的产品采用r8610平台,内核版本linux-2.6.9,文件系统squashfs,我是第一次听说这个文件系统的。用redboot引导的linux。
先说说移植新内核的前提吧。板子上flash是4M的,而这个板子所在的设备需要大量存储实时数据,所以采用u盘来存储。但是u盘会不定时down掉,时间间隔不定,2礼拜或者更长。研究了一段时间内核,usb部分和文件系统部分,不好定位。后来要在这个设备上添加一个usb转串口来通信的功能。采用pl2303,内核自带pl2303驱动,所以直接直接写应用就可以,发现读正常,写不正常,close串口以后,再次打开发送的第一帧数据丢失。后来在驱动中层层跟踪,定位是ohci-hcd的问题。看了几天这部分代码。水平不到位。没发现什么异常。给几年前提供这个芯片的厂商打电话咨询,说可能是内核支持的问题。提议用linux-3.0.4,他们实验过,直接编译就可以运行起来。然后让我试试看是否usb是否还有类似的问题。
于是,开始移植。
开始只移植了linux-3.0.4的内核,但是老的文件系统怎么都起不来。厂商技术人员说确定可以直接编译就能起来。后来仔细阅读串口输出,和原来设备上跑的系统相比较,定位到可能flash分区不一样的原因。抱着试试看的态度修改/drivers/mtd/maps/pyhsmap.c文件。修改物理分区map表。经过多次试验,文件系统终于挂上。分析原因,厂商的flash不用分区。他们的flash分区信息是通过redboot传递的,而我们用的redboot没有传递这个信息。所以内核找不到根文件系统。
挂上以后,也不是一马平川就到头了。显示squashfs有问题。然后接下来又是几天的乱搞。只要串口输出有一点和上次不一样的地方就十分高兴。在添加了无数打印以后。发现制作文件系统的工具版本太低造成的。Linux-3.0.4中squashfs支持的文件系统是4.0以上版本。而我采用的是2.x版本。
然后 sudo apt-get install新版本工具,编译,下载,启动,涛声依旧。只是有一点进展,但是并没有看见需要登录的界面。
没有办法,这样不好搞,不好定位,干脆直接编译个新链子吧。说敢就干。从上下载一个比较新的buildroot版本,tar解压,make
menuconfig,make出错,需要安装好多小工具才能正常make。我的电脑缺 bison, flex, gettext, texinfo文件,sudo apt-get install这些就可以啦。
第二阶段,制作新工具链和文件系统
记录时间:2012-5-30
记录内容:采用buildroot制作新工具链和新文件系统
所选各个插件的版本:
linux-3.0.4
busybox-1.19.4,
gcc-4.4.6
buildroot-2012.02
在buildroot根目录执行make menuconfig,进入toolchain项,我的修改如下图:
Kernel Header选择和我的所用的内核版本一致。然后是uClibc,binutils,gcc等。然后保存退出,make即可。
在buildroot里面没有配置编译linux内核。因为buildroot里面对内核的选择只有linux-3.0.x
,没有明确可以指定3.0.4.并且还可以省点时间下载。等新链子出来,直接用新链子编译内核就是了,效果和在buildroot里面效果一样。
buildroot的主要工作是制作内核镜像,工具链和文件系统rootfs文件夹的产生。通过这个称为工具的东东可以很方便的制作内核,工具链,文件系统,而不用直接对某一部分进项单独的配置和修改。直接在buildroot根目录执行make就可以生成我们需要的各种东东。不用我们自己去下载,配置,编译。基本可以说一键搞定。
make执行以后,如果第一次编译的话,根据host主机和网络情况,会耗费一定时间,一半比较长。而第一次以后执行make就很快了。
make执行以后,相对我们来说有用的目录只有1个,buildroot/output下的东东有很多是我们需要的。
好像以前的buildroot版本的生成的目录不是这个,反正不管什么版本,直接从文档可以查看各个目录说明。
buildroot-2012.02版本的output目录是这样的:
1 build目录是下载以后解压的各种解压包,我在buildroot根目录执行make menuconfig的时候选择busybox-1.19.4,那么这里就有busybox-1.19.4的解压以后的包。
2 host目录,万分重要的一个包。编译出的工具链就在这里,上说在这个目录下的bin目录下是工具链,但是我编译完以后,host下面没有bin目录,还好有usr目录。到usr下面一看,还好,usr/bin目录下有很多工具链,就是它。记下路径,以备后用。后面我编译内核的时候就是用的这个链子,不错,挺好用。我们没有在duildroot环境下直接编译内核,其实在duildroot环境下也可以直接编译linux内核,在buildroot根目录执行make linux-menuconfig就可以对所选内核进项配置,然后make以后,也在这个output目录下就会有bzImage产生。
3 images目录,这是个对开发者感觉挺爽的目录,因为整个buildroot环境make以后的结果都在这里。我测试的时候在buildroot选项有linux内核,文件系统选择squashfs,那么在这里就会有bzImage---内核,rootfs.squashfa---文件系统。这两个东西直接下载到板子上就可以启动啦!!
4 staging这个目录不关注,省略。
5 target目录,又一个十分重要的目录。这个目录就是制作文件系统的目录。你可以把它打包,然后想搬到哪都行,再然后用你熟悉或者特定的工具做成适合自己的文件系统。我把这个目录从这里取出取,然后放在我的工作目录,用我自己的文件系统生成工具做成适合我的板子的文件系统。下载,爽,直接启动。
6 toolchain,里面东西也是一大堆,暂时不知道有什么用,所以略。
在buildroot根目录下执行make menuconfig可以对buildroot进项配置。目前的修改基本可以告一段落。如果还需要修改的话,也就只有buildroot中的busybox修改,在buildroot根目录执行
make busybox-menuconfig就可以对buildroot环境
由于有了buildroot编译出来的新的工具链,所以用新工具链来编译3.0.4内核。
在根目录下修改Makefile,CROSS_COMPILE ?= buildroot编译出的工具链的路径。然后make,在arch/x86/boot目录下就有bzImage文件,
然后把新内核,新文件系统下载到flash,然后reset。一路畅通,直到出现下面的界面。我那个乐啊。
终于到了期待已久的login阶段
Root+enter
第三阶段,把改添加的服务都设置启动
No.1 配置telnet
使用busybox自带的telnetd服务。
1 在busybox根目录执行make menuconfig的时候,选择上telnetd服务。Make install。然后将make install 后生成的linuxrc文件,以及bin,sbin目录中的软连接文件拷贝到rootfs对应文件夹目录下。将make install后在sbin目录中生成的telnetd文件拷贝到rootfs/usr/sbin目录下。
2 修改几个文件passwd,group, shadow
我的修改如下:
Passwd:root:u6NZXPyRSM/SM:0:0:root:/:/bin/sh(密码stc2000)
Group: root:x:0 (不知道什么意思)
Shadow:删除root所在行
注意:还有个注意点啊,securetty文件,这个文件时限制root登陆的文件。默认是不允许telnet以root身份登录的,所以把这个文件改名字,也可以修改,添加pts/0,pts/1,
Pts/2,pts/3,pts/4,pts/5,pts/6,pts/7即可。
3 编译内核的时候需要选上
还要选上proc,sys,devtps文件系统。编译内核,重新制作根文件系统,启动。telnet登陆,用户名:root,密码stec2000.和串口登陆一样。搞定。
NO.2 配置vsftpd
1 我的vsftpd是在buildroot里面选择编译生成的,编译以后,自动出现在/usr/sbin/目录下有vsftpd可执行文件。
2 我的板子的情况是需要在/usr/share/目录下建立empty文件夹。
3 确保系统中游nobody用户,这个是tftp需要的,具体为什么我就不清楚了,反正没有不行
4 在/etc/目录下须有 vsftpd_chroot_list文件,如果没有这个文件,即使密码输入正确也不能登陆。这个文件内容如下:
Root
Nobady
Admin
ftp
5 在/etc/目录下建立vsftpd.conf文件,根据网上的帖子修改这个文件即可。我的文件内容如下:
anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=022
#anon_mkdir_write_enable=YES
dirmessage_enable=YES
xferlog_enable=YES
connect_from_port_20=YES
chroot_list_enable=YES
tcp_wrappers=NO
listen=YES
6 运行vsftpd,在浏览器输入:ftp://ip。回车,ok,搞定。输入用户名和密码,这里的用户名和密码和串口终端输入的一样。顺利登陆。
NO.3 u盘挂载部分
由于目标板flash比较小,只能放下redboot,kernel和rootsys,应用程序挺大,所以采用u盘挂载的方式。
1 在编译内核的时候,usb支持部分要选上,scsi也有部分要选上,还要选上支持hotplug。
2 在buildroot中执行make busybox-menuconfig的时候,要选上支持mdev
3 把buildroot/output/下的target目录取出来,我们就用这个目录做根文件系统。
在target/etc/目录下建立mdev.conf文件,这个是热插拔usb的时候需要的脚本。
我的mdev/conf内容如下:
Sd[a-z][0-9] 0:0 660 *(/etc/automount.sh $MDEV)
就是说有热插拔的时候,实际执行的是/etc/目录下的automount.sh脚本
我的automount.sh文件内容如下:
#!/bin/sh
# mount the /dev/sd* to /mnt/doc
echo -e "hello" >> /tmp/mdev.log
echo -e "$1" >> /tmp/mdev.log
if [ "$1" == "" ]; then
exit 1
fi
mounted=`mount | grep $1 | wc -l`
echo $mounted >> /tmp/mdev.log
if [ ! -d /mnt/work ]; then
echo -e "/mnt/work is not exist" >> /tmp/mdev.log
exit 1
fi
# If mounted, we will umount it
if [ $mounted -ge 1 ]; then
echo -e "mounted we umount it" >> /tmp/mdev.log
if ! umount "/mnt/work"; then
umount -l /mnt/work
exit 1
fi
else
echo -e "not mounted ,we will mount it" >> /tmp/mdev.log
fsck.ext3 /dev/$1 -p
if ! mount "/dev/$1" "/mnt/work" -o sync ; then
echo -e "mount err" >> /tmp/mdev.log
exit 1
fi
echo -e "mount success" >> /tmp/mdev.log
fi
exit 0
4 然后需要在启动脚本里加入这个几句:
null::sysinit:/bin/echo /sbin/mdev > /proc/sys/kernel/hotplug
null::sysinit:/sbin/mdev –s
在添加上面两句以前,要保证已经mount 了proc,sys,devpts文件系统。
开始我把这两句话添加到inittab文件里,启动以后发现如果u盘在上电以前查到板子上,上电以后是不会自动加载的,但是上电以后,如果插拔u盘是可以执行automount.sh的。
后来把这两句添加到rcS文件里,问题解决,u盘在任何时候都可以检测到插拔并且执行对应脚本。
NO.4 移植e2fsprogs
flash根文件系统是只读的,而设备在运行的时候需要记录数据,数据量挺大,并且应用程序都存储在u盘上。所以必须保证u盘上数据的正确性。而当u盘非法卸载或者带电强行插拔的话,u盘上的数据或者超级快上的数据会损坏,所以每次挂载u盘以前最好check一下并且恢复。
说到这个check文件系统,ext2文件系统check需要的是时间比较长,而ext3需要的时间要短许多,所以我们采用u盘上采用ext3文件系统。
移植这个工具,可把俺累的够狠。几乎一新期都在折腾这个东西。因为故障不好定位,所以感觉很迷惘,无头绪的80后啊,实在不幸,让俺赶上啦。还好俺比较卖力,经过几天的努力,把事情搞定。
1 首先明确编译e2fsprogs要用对应buildroot产生的工具链
2 一般在e2fsprogs目录下建立两个目录,一个是编译的目录,另外一个是编译结果存放的目录。比如我的e2fsprogs采用版本1.42.3版本。进入e2fsprogs-1.42.3目录,然后mkdir workdir result。
3 Cd workdir,然后执行:
../configure CC=/home/lifeng/disk1/buildroot/buildroot-2012.05/output/host/usr/bin/i386-linux
-gcc --enable-elf-shlibs --disable-defrag --host=i386-unknown-linux-uclibc --prefix=/home/lifeng/r8610/e2fsprogs1423-1205/result/
其中CC就是buildroot编译出来的工具链,绿色的部分表示编译出的结果采用共享库的形式,红色的部分是我噩梦的部分,这部分是关于ext4的部分,可能制作工具链的时候选择的各个插件版本不同,对ext4支持不同导致,就是下面的各个插件版本。也可能不是这个原因。。。
后来仔细看帮助,干脆去掉这部分算啦,我们用的ext3,所以去掉这部分影响也不大。Host参数表示我们编译出的工具用在什么平台。我是这样确定的。在buildroot编译完成以后,找到编译完的工具链,如我的工具链在buildroot/output/host/usr/bin目录下,下图是截取的一部分。
然后执行i386-linux-gcc –v,显示如下:
其中红色的部分是buildroot编译工具链的时候的configure的三个参数。
Build,host,target。Configure时候的三大参数。
下面简单说明一下: |
1. build 就是你现在使用的机器。 |
2. host 就是你编译好的程序能够运行的平台。 |
3. target 编译程序能够处理的平台。一般都用在构建编译本身的时候(gcc), 才用target, 也就是说平时我们所说的交叉编译用不到target. |
比如: 在386的平台上编译可以运行在arm板的程序 ./configure
--build=i386-linux,--host=arm-linux就可以了. |
因为一般我们都是编译程序而不是编译工具.
而我们上面的是编译工具链,就用到了target参数, |
我们上面红色的部分意思就是说:(build)在386平台上编译工具链,(host)这个工具链运行在i386平台上,(target)而这个工具链可以编译处理运行在i386-unknown-linux-uclibc平台上程序。
回到我们的e2fsprogs中的CC参数:
上面工具链的target参数就是我们的host参数,其它不用指定。
--prefix参数指我们编译以后的安装目录。
执行上面的配置命令以后依次执行下面命令:
Make
Make install
Make install-libs
进入prefix指定的安装目录。看下面的截图:
Lib目录下的内容:
Sbin目录下的内容:
以上两个目录下的内容就是我们需要的东西,然后根据需要把sbin目录下的命令工具拷贝到我们的根文件系统目录下,比如我们需要fsck.ext3.就把fsck.ext3拷贝。然后看以下这个工具需要的动态库:
I386-linux-readelf –d fsck.ext3
需要6个动态库,那么把上面lib库下的对应库也拷贝到根文件系统的/lib目录或者/usr/lib目录下。
移植e2fsprogs就大功告成啦!!
注意:
1 用mksquashfs制作文件系统的时候要把上次产生的文件系统镜像先删除了。要不下载到板子会出现下面的情况,原因不明。
2 编译buildroot的时候,如果在busybox里面需要sqlite3的支持,必须在第一次编译工具链的时候选上下面这一项。
否则编译sqlite3的时候会报错。
如果一旦以为sqlite报错的话,我没有其它办法,除了make clean以后,重新配置。吧要选的都选上,然后执行make,生成的文件系统buildroot/output/target/相关目录下面就有对应的库和可执行程序啦。
3 在busybox里面如果要选择fdisk命令,也必须在开始选上,busybox默认没有选。我的执行顺序是make menuconfig,选择工具链需要的各个版本。然后如果在执行make busybox-menuconfig的时候不选fdisk,那么在工具链编译好以后,在执行make busybox-menuconfig的时候选上fdisk,编译会出错。
如果在最开始执行make menuconfig,选择工具链需要的各个版本。然后紧接着执行make busybox-menuconfig的时候选上fdisk。编译则没有任何问题。
如果你已经到了发现编译fdisk出错的地步了,我的操作是执行make clean。然后重新执行make menuconfig,然后执行make busybox-menuconfig的时候选上fdisk。就可以啦。
4 几条redboot操作命令:
Load –r –v –h 192.168.0.241 –m tftp –b 0x400000 firmware.bin下载命令
Dflash –s 0x400000 –d 0xffc00000 –l 0x3c0000
5 2012-6-21,由于u盘上文件系统可读写,所以每次挂载以前都要fsck一下,以防上次是非法断电造成数据不一致,但是在对u盘进行fsck.ext3的时候,发现后半部分block地址都错误。开始我怀疑是用pc上的mkfs.ext3制作的文件系统在目标板上fsck就会发生这种现象,所以打算直接用目标板上的mkfs.ext3制作u盘上的文件系统。发现也出错。并且出错的block的地址大概处于整个block数量的一半处,这个时候我怀疑是否支持这么大的单个文件系统。我的u盘是4g的,好像编译busybox的时候又个选项是2g的文件大小选项。为了再次验证是否是文件系统太大造成这个情况。我在目标板上把4g的flash分成3个区,每个都小于2g,重新运行fsck.ext3,OK。看样确实是和单个文件系统大于2G有关。于是重新编译工具链和busybox,接下来继续验证。
2012-6-25,今日添加一些东西,如下:
1 buildroot的修改,编译buildroot的时候,可以选择e2fsprog,所以也就不用在外面单独编译e2fsprog了,效果一样,只是整体编译完后会小一点。现在我用的的e2fsprog目录在buildroot:/home/lifeng/disk1/buildroot/buildroot-2012.02,现在已经配置好了,如下:
a)工具链选项要选上支持大于2G的文件
b)在dingc选下面选项,进入
e)直接make,
然后在/home/lifeng/disk1/buildroot/buildroot-2012.02/output/target下面的usr/sbin目录下就有fsck.ext2,fsck.ext2等工具。
另外对应的库也已经在/home/lifeng/disk1/buildroot/buildroot-2012.02/output/target下的/usr/lib目录下。