您的位置:首页 > 其它

使用busybox-1.16.1,mkfs.jffs2制作jffs2文件系统

2014-02-21 09:38 597 查看
          需要为hi3531板子上的spi flash 做一个jffs2的文件系统, 看了好多资料都不够全面,特别是添加文件系统文件的部分都写的很乱,现在先总结一下思路,再详细介绍.
1. 安装配置busybox
2. 创建和修改jffs2文件系统中的文件
2.1 自己创建
2.2 使用已有文件系统修改
3. 使用mkfs.jffs2制做文件系统
4. 文件系统优化

一.编译并生成根文件系统文件

1.解压该包

tar -jxvf busybox-1.16.1.tar.bz2

cd busybox-1.16.1

2.修改Makefile

找到

CROSS_COMPILE ?=

修改为CROSS_COMPILE ?=arm-linux-

?=  表示若之前未赋值,则赋值为

找到

ARCH ?= $(SUBARCH)

修改为

ARCH ?= arm

3.进行默认配置

make defconfig

4.对配置信息进行修改

make menuconfig

检查Miscellaneous Utilities--->

    taskset 是否已经去除   (不去除就编译不过的)

同时设置如下:

Busybox Settings --->

        Build Options --->

            [*]Build BusyBox as a static binry (no shared libs)      
使用静态库,就不用拷贝交叉编译文件到/lib下了     

        Installation Options --->

            [ ]Don't use /usr

 有人说是不选会覆盖/usr文件夹,其实是在文件系统中生成一个 /usr 目录的意思,我们需要 /usr 文件夹,所以不要选             

 
#make
#make install
所生成的文件就在当前目录的 _install目录下。
 
二.准备制作jffs2文件系统的所有文件

(一) 自己创建

编译结束后,自己随便找个目录,并在该目录下建立rootfs文件夹

并在其中建立如下路径

1.  #mkdir bin sbin lib etc dev mnt usr/bin usr/sbin usr/lib proc sys -p

2.  把刚才编译busybox生成的在_install目录下的文件全部copy到rootfs/目录下,注意用 cp命令带 –arf 参数

3.加入运行需要的库文件

写了一个脚本,把这个放在/usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/lib/下执行,目的是将一些程序运行时需要的函数库复制到目标文件系统的lib路径下

=========以下是脚本内容===================

#!/bin/bash

#You should put this file cp.sh in $(CROSS-COMPILE)/lib/

ROOTFS_LIB=${PROJECT}/rootfs/rootfs_1.13/lib/

for file in libc libcrypt libdl libm libpthread libresolv libutil

do

cp $file-*.so ${ROOTFS_LIB}

cp -d $file.so.[*0-9] ${ROOTFS_LIB}

done

cp -d ld*.so* ${ROOTFS_LIB} 

#end script

=============脚本结束========================

4.在 rootfs/etc/下建立如下文件或者路径
4.1.

vi fstab

内容是:

proc /proc proc defaults 0 0

sysfs /sys sysfs defaults 0 0

4.2.

vi proflie 

内容是:

#!/bin/sh

#You should put this file profile into your $(CONFIG_PREFIX)/etc/

echo "Set seaech library in /etc/profile"

export LD_LIBRARY_PATH=/lib:/usr/lib

echo "Set user path in /etc/profile"

export PATH=/bin:/sbin:/usr/bin:/usr/sbin

alias ll='ls -l'

/sbin/ifconfig eth0 218.192.161.80 netmask 255.255.255.0

/sbin/ifconfig lo 127.0.0.0

echo "Configure net done"

4.3.

mkdir init.d

cd init.d

vi rcS

内容是

#!/bin/sh

/bin/mount –a
/bin/sh  /*这个一定要,不然进不了控制台*/
 
(执行chmod 777 rcS)
 
4.4. 在etc下创建文件inittab,内容如下;
console::sysinit:-/etc/init.d/rcS
 
4.5. 在rootfs/dev下面建立两个节点
#mknod -m 660 console c 5 1

#mknod -m 660 null c 1 3

这样就差不多大功告成了

补充说明:
1.在上文第二节的4.2小节中如果rcS缺少了/bin/mount –a那一句,那么启动后,总是出现如下提示

can't open /dev/tty2: No such file or directory

can't open /dev/tty3: No such file or directory

can't open /dev/tty4: No such file or directory

在源码路径下 grep "can't open" * -r

最后发现在init/init.c文件中有问题

经过分析,原因在于如下3句,

694        new_init_action(ASKFIRST,bb_default_login_shell,VC_2);

695        new_init_action(ASKFIRST,bb_default_login_shell,VC_3);

696        new_init_action(ASKFIRST,bb_default_login_shell,VC_4);

这三句会启动三个虚拟终端,如果你觉得你的的板上没这个必要,可以注释掉。

(二) 使用已有镜像创建

在这里,为了避免重新制作文件系统,我采用了英蓓特公司的MBS-SAM9G45开发板自带的jffs2文件系统Angstrom-x11-image-demo-glibc-at91.rootfs.jffs2。在整个制作jffs2文件系统的过程中,我们采用root权限。
2.1.   挂载文件系统镜像
jffs2文件系统不是块设备,不能直接mount,需要做一些中间步骤。首先,内核必须支持MTD,并且编译了mtdram、mtdblock这两个模块。先先建立一个大于等于要挂载的文件系统的虚拟mtd设备。Angstrom-x11-image-demo-glibc-at91.rootfs.jffs2文件系统为28.2M,那么我先建立一个大于等于28.2M的虚拟mtd设备。(为了避免制作过程当中向文件系统里边添加大文件,我将mtd大小设置为50M*1024=50720K)
$ sudo modprobe mtdram total_size=50720
其中,total_size的单位是KB,指定mtd的大小。
加载mtdblock产生虚拟块设备并把Angstrom-x11-image-demo-glibc-at91.rootfs.jffs2的内容写入生成的虚拟设备中:
$ sudo modprobe mtdblock
$ sudo dd if=/home/Embest_SAM9G45/Angstrom-x11-image-demo-glibc-at91.rootfs.jffs2 of=/dev/mtdblock0
(注:dd命令是指定大小的块拷贝文件,并在拷贝的同时进行指定的转换。if=file:输入文件名,缺省为标准输入。of=file:输出文件名,缺省为标准输出。)
创建挂载点:
$mkdir /mnt/mtd
现在就可以mount了:
$ sudo mount -t jffs2 /dev/mtdblock0 /mnt/mtd
进入/mnt/mtd之后即可对文件系统进行修改!
2.2.   制作jffs2文件系统镜像

三. 制作jffs2文件系统
1.       使用mkfs.jffs2
mkfs.jffs2 -r rootfs -o rootfs1.jffs2 -e 0x4000 --pad=0x1000000 -s 0x200 –n

生成的文件rootfs.jffs2就是要烧写的文件系统
0x4000 = 16k
注意:--pad=0x1000000  (16M)这个值应该跟你文件系统分区的大小一样。
2.       我的linux启动参数 (Boot options):
mem=M root=/dev/mtdblock2 init=linuxrc console=ttySAC0 rootfstype=jffs2

修改(在后边一步讲)好自己的文件系统后,退到已做好的文件系统目录的上一级。比如我的文件系统的挂载点是/mnt/mtd,则退到/mnt目录下,用mkfs.jffs2工具制作jffs2文件系统,如下:
#mkfs.jffs2 -r rootfs -o fs.jffs2 -e 0x20000 --pad=0x500000 -s 0x800 –n -l
0x20000 = 64k 0x500000=5M
即可生成要烧写的文件系统rootfs.jffs2
Mkfs.jffs2各参数的意义如下:
-r:指定要做成image的目录名。
-o:指定输出image的文件名。
-e:每一块要擦除的block size,默认是64KB.要注意,不同的flash, 其block size会不一样,三星的K9F2G08U0A的block size为0x20000(从其datasheet里可以找到)。在没有加-e选项是,启动会出现以下错误:at91sam
user.warn kernel: Empty flash at 0x00f0fffc ends at 0x00f10000。因此,若有类似的错误,加上-e选项,并配置nandflash的块大小,即可消除。
--pad(-p):用16进制来表示所要输出文件的大小,也就是fs.jffs2的大小,如果实际大小不足此设定的大小,则用0xFF补足。也可以不用此选项,生成的文件系统的大小跟本身大小一致,暂时还不知道有和妙用,但是加上后会少出现很多错误。
-n,-no-cleanmarkers:指明不添加清楚标记(nandflash有自己的校检块,存放相关的信息)。如果挂载后会出现类似:CLEANMARKER node found at 0x0042c000 has totlen 0xc != normal 0x0的警告,则加上-n就会消失。
-l,--little-endian:指定使用小端格式。
还有的选项,不需要了,可以自己看帮助!用如下命令mkfs.jffs2 –h。

四 文件系统优化
   需要优化的原因
1、  系统在启动时,会启动很多的项目,而很多的进程是我们根本不需要的,通过对文件系统的修改,可以减少启动项,加快开机速度。
2、  由于开发板提供的文件系统很全面,囊括了声卡、显卡、游戏、液晶显示屏等很多驱动,但是这些都是我所不需要的,因此通过修改文件系统,我们可以裁减掉不需要的驱动、库文件以及所有的配置文件。
3、  在系统启动时,需要加入我们自己启动程序。在这个文件系统中,加入了超级用户自动登录功能、无线网卡驱动自启动以及和FPGA的接口驱动自动加载。
3.2.   删除多余的启动项
所有的启动项都在init.d中实现,按照不同的runlevel,分布在rc0.d~rc6.d以及rcS.d中。rc?.d和/etc/init.d的关系,在下边这篇文章中叙述的相当详细,可以参考学习:
http://wenku.baidu.com/view/8bdb9237ee06eff9aef8071b.html
rc?.d中都是指向/etc/init.d中脚本的连接。在rc?.d中,可以看到有K和S开头的两种连接。S开头表示启动,K开头表示不启动。在启动时,系统会执行rc?.d中的所有S开头的所指向的脚本文件。因此,我们只需要修改rc?.d中的连接以及/etc/init.d中的脚本文件,就可以修改启动的项目。
在本文件系统中,我做了如下修改:
rc2.d:关闭S50usb-gadget。
rc3.d:关闭S50usb-gadget、S10alsa-state、S10dropbear。
rc4.d:关闭S50usb-gadget。
rcS.d:关闭S00psplash(旋转进度条,显示开机的进度)、S02banner。
我用的关闭的方法是mv S50usb-gadget K50usb-gadget,这样就关闭了usb-gadget,在需要启动此项时,也很方便启动。当然,这样的操作并没有大幅度减小启动的时间。
3.3.   root用户自动登录
在每次设备启动或者复位的时候,都需要手动在启动结束后输入root以登录系统,而在无人值守的情况下,需要root用户能自动登录,并执行程序。在/etc/inittab中做如下修改即可实现root用户自动登录:
默认启动runlevel为5,即id: 5 :default
注释掉登录的那行代码,即#S:2345:respawn:/sbin/getty 115200 ttyS0
添加如下登录代码:S1:2345:respawn:/sbin/getty /usr/bin/autologin 115200 ttyS0。启动autologin程序需要自己完成,/usr/bin/是autologin所在位置,这个位置可以自己任意选取。
编写autologin.c程序如下:
#include <stdlib.h>

#include <stdio.h>

 

int main ( )

{

execlp(“login”, “login”, “-f”, “root”, 0);

}

然后编译autologin.c,注意要使用交叉编译器。
$ /usr/local/arm-2007q1/bin/arm-none-linux-gnueabi-gcc –o autologin autologin
将编译好的autologin可执行文件复制到/usr/bin目录下。也可以放到其他目录下,相应的修改/etc/inittab即可。
至此,重新制作文件系统镜像后,烧写进nandflash,即可自动登录root用户。
3.4.   添加自己的启动项
因为rcS是每个系统都必须启动的项,因此在rcS中添加启动项是最直接的方法。(在我们的系统的中没有rc.local文件,网上有很多在rc.local中添加自启动的方法)
我需要自动加载无线网卡驱动、FPGA接口驱动以及开启DHCP服务。
首先,将无线网卡和FPGA的驱动以及DHCP的可执行文件以及配置文件拷贝进相应的文件夹(可执行放的文件夹可以自己设置,在写执行脚本的时候注意路径,配置文件需要按规则放)。在这里,我将无线网卡驱动rt3070sta.ko拷贝到/usr/src中,rt3070sta.ko驱动加载后需要读取的配置文件RT2870STA.dat放在/etc/Wireless/RT2870STA中。将FPGA的接口驱动fpgadev拷贝到/usr/src。在编译内核时,已经添加了dhcp服务,因此在/sbin和/usr/sbin中分别放有客户端uhdpc和服务端uhdpd,拷贝配置文件udhcpd.conf到/etc下,在/var/lib/misci下新建(touch命令)一个文件udhcpd.leases。修改所有文件的权限为755(chmod
755 xxx)。
其次,需要在/etc/init.d中添加执行的脚本文件,在此脚本文件中添加你要执行的代码。编写autoset_sta脚本如下:
#!/bin/sh

 

#Auto set wireless card and FPGA driver

/sbin/insmod /usr/src/rt3070sta.ko

/sbin/insmod /usr/src/fpgadev.ko\

 

/sbin/udhcpc

最后,修改文件权限并在rcS.d中添加指向init.d/autoset_sta的连接。
$ chmod 755 autoset_sta
$ cd ../rcS.d
$ ln –sf ../nit.d/autoset_sta S99autoset_sta
制作好文件系统后,烧写重启即可自动加载这些驱动以及服务。
3.5.   减小文件系统体积
原始文件系统28.2MB,在加上自己的文件后,达到了30MB。嵌入式下存储资源是宝贵的,为了减少所占资源,必须对文件系统进行瘦身。
进入/etc,删除不必要的启动脚本文件,比如X11的文件。
进入/lib,删除比需要的库文件。
进入/usr,删除games。
进入/usr/bin,删除没用的命令。
进入/usr/lib,删除没用的库文件。这里库文件相当多,达到16M之巨,而里边大多是我们不用的库,例如libaudiofile.so.0、libsoundgen.so.0、libmad*、libICE等,还有关于图像和界面的库等,这些都可以删掉。全部删除后,/usr/lib可以小到3M~6M。当然,这都得看具体应用,对与我来讲,我所用到的就是网络编程、多线程、无线网卡、SPI通信、串口通信等东西,所以能删除很多不必要的库。但是因为启动项删除的不够干净,在启动的过程当中,仍然会用到/usr/lib中的很多库,因此会出现很多错误,但并不影响我的操作。
进入/usr/share,删除没有用的doc以及applications。。。。。
基本裁剪已经差不多了,重新编译文件系统,输出的大小为16M左右。
(还需要好好把系统的整个启动已经程序的调用搞清楚一下,这还可以大大的裁剪)
4.       问题及解决方法
Q:在启动过程中出现at91sam user.warn kernel: Empty flash at 0x00f0fffc ends at 0x00f10000问题
A:在mkfs.jffs2的时候,加上-e 0x20000指定擦除块的大小。-e是指定擦除块的大小,我们使用的nandflash的块大小为128K字节,因此-e后的参数为(128*1024)10=(20000)16。
 
Q:启动的时候出现CLEANMARKER node found at 0x00f10000 has totlen 0xc != normal 0x0问题。
A:在mkfs.jffs2的时候,加上-n选项。-n, --no-cleanmarkers。指明不添加清楚标记(nand flash 有自己的校检块,存放相关的信息。)如果挂载后会出现类似:CLEANMARKER node found at 0x0042c000
has totlen 0xc != normal 0x0 的警告,则加上-n 就会消失。
 
Q:解决jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x01649298: 0xa25e instead问题的方法
A:在mkfs.jffs2的时候加上-s 2048(页大小,由芯片决定)以及-l(小端模式)两个选项。-s是指明页的大小,我们使用的nandflash的页的大小为2048字节。-l指明为小端模式,一般嵌入式下均为小端模式。
 
说明:
1、  在文件系统制作的过程,均需要使用root用户权限;
2、  一般嵌入式下只有root用户登录,因此文件系统中的所有文件都需要具有root可执行权限,如果用其他用户登录,请保证文件系统中文件(特别是自己添加的文件)的相应可执行权限。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: