八,裁剪linux3.19.9内核,制作jffs2和yaffs2根文件系统

时间:2024-01-21 09:14:34

文档时间:2018-08-20

交叉编译器:arm-linux-gcc-4.3.2

Ubuntu版本:16.04

kernel版本:linux-3.19

 

1,裁剪Linux3.19.9内核

在内核目录下执行 make menuconfig 命令:

1),去掉跟2440无关的单板支持,进入System Tye:

进入 SAMSUNG S3C24XX SoCs Support,设置如下:

2),文件系统的裁剪

进入 file system 选项,然后裁减掉不相关的文件系统:

3),device drivers 的裁剪

进入 Device Drivers -->Network device support-->Ethernet driver support,除了 DM9000的配置,其他的都裁减掉:

4),去掉声卡的支持

裁剪完毕,输入 make uImage 编译,编译出来的 uImage 大小如下:

 

2,构造根文件系统

1)编译、安装、配置 busybox

busybox源码下载地址:https://busybox.net/downloads/

 下载 busybox-1.23.0 版本,输入以下命令进行配置:

tar -xjf busybox-1.23.0.tar.bz2
cd busybox-1.23.0
make menuconfig

出现如下界面:

进入 Busybox Settings--->Build Options--->Cross Compiler prefix 设置交叉编译器,设置如下:

进入 Busybox Settings--->Installation Options ("make install" behavior)--->BusyBox installation prefix 设置安装目录,设置如下(此处不设置也可以):

设置完成后,输入以下命令进行编译安装:

make
make install 

 如果之前没有配置安装目录,则命令如下:

make
make install CONFIG_PREFIX=/home/aaron/work/rootfs/fs_new    //指定安装位置

2),添加库文件

进入到交叉编译器所在目录:

cd /usr/local/arm/4.3.2

 通过命令 find -name lib 找到如下库文件:

由于 arm9 属于armv4t 架构,所以把上面红线标注的库文件拷贝到 fs_new 目录下对应的文件夹中,命令如下:

mkdir /home/aaron/work/footfs/fs_new/lib
mkdir /home/aaron/work/footfs/fs_new/usr/lib -p  
cp arm-none-linux-gnueabi/libc/armv4t/usr/lib/*.so* /home/aaron/work/footfs/fs_new/usr/lib -d           /* -d:保持链接 */
cp arm-none-linux-gnueabi/libc/armv4t/lib/*.so* /home/aaron/work/footfs/fs_new/lib -d

 3),构造 etc 目录

在 fs_new 目录下新建 etc 目录,mkdir etc,在etc目录下需要构造以下三个文件:

etc/inittab---init进程根据此文件来创建其它紫金城

etc/init.d/rcS---脚本文件,用来执行相关命令,如使用 mount -a 来挂载 etc/fstab 文件中需要挂载的文件系统

etc/fstab---保存需要挂载的文件系统

(PS:这些文件可以自己构造,也可以从busybox目录下拷贝相应的模板,然后加以修改)

inittab 文件中内容如下:

::sysinit:/etc/init.d/rcS    //内核启动时,执行/etc/init.d/rcS
console::askfirst:-/bin/sh  //启动console对应的-/bin/sh进程之前,等待用户按enter键
::ctrlaltdel:/sbin/reboot   //按下ctrl+alt+del组合键时,启动reboot命令
::shutdown:/bin/umount -a -r  //系统关机前,卸载所有文件系统

rcS 文件中内容如下(需要增加可执行权限 sudo chmod +x ...):

mount -a               //装载/etc/fstab中的文件系统
echo /sbin/mdev > /proc/sys/kernel/hotplug  //使/sbin/medv指向hotplug,从而支持热拔插
mdev -s                //使用medv命令自动创建/dev下的所有设备节点

fstab 文件中内容如下:

proc           /proc        proc     defaults      0     0
tmpfs          /tmp         tmpfs    defaults      0     0
sysfs          /sys         sysfs    defaults      0     0
devpts         /dev/pts     devpts   defaults      0     0

4),构造其它文件和目录

创建其它目录:

mkdir dev mnt proc tmp sys root

创建终端文件:

sudo mknod –m 660  dev/console c 5 1
sudo mknod –m 660 dev/null c 1 3

 

3,制作 .jffs2 文件系统映像

直接使用 mkfs.jffs2 命令即可,如果不支持 mkfs.jffs2 命令,输入 sudo apt-get install mtd-utils 安装即可:

cd /home/aaron/work/rootfs
mkfs.jffs2 -n  -s 2048  -e 128KiB  -d fs_new  -o fs_new.jffs2
//-n:表示每块不添加清除标记,-s:NAND的每页为2k,-e: NAND的每块为128kb
//-d fs_new:表示要制作的根文件系统文件
//-o fs_new.jffs2:表示生成的映像文件

然后在uboot中输入以下命令烧写测试(内核已经烧写到指定位置):

tftp 30000000 fs_new.jffs2
nand erase.part rootfs
nand write.jffs2 30000000 4a0000  $filesize
set bootargs console=ttySAC0,115200 root=/dev/mtdblock3 rootfstype=jffs2
reset

 

4,制作 .yaffs2 文件系统映像

1),首先获取 yaffs2 源码

cd /home/aaron/work/rootfs
git clone git://www.aleph1.co.uk/yaffs2

2),将 yaffs2源码配置到内核里,使内核支持 yaffs2文件系统(如何安装可以查看 README-linux 文件)

cd yaffs2 
./patch-ker.sh  c m /home/aaron/work/kernel/linux-3.19//c:将yffs2文件夹copy到linux-3.19/fs里, m:指定多版本

进入内核,查看 fs 目录下的内容:

可以看出 yaffs2 已经安装进去了,在内核里修改配置项,使其支持yaffs2文件系统:

cd /home/aaron/kernel/linux-3.19
make menuconfig

 

配置上即可,然后重新编译内核,make uImage,出现以下错误:

搜索 dentry 关键字,发现在 file 结构体中 path 结构体里定义:

修改代码,在 yaffs_vfs.c 中加上下面一句:

#define f_dentry f_path.dentry

编译成功

 3),使用 mkyaffs2image 命令制作 yaffs2 文件系统

cd /home/aaron/work/rootfs
mkyaffs2image  fs_new  fs_new.yaffs2

mkyaffs2image 可以使用板子自带的,也可以自己生成,在 yaffs2 目录下,进入 utils 目录,输入 make 即可生成 mkyaffs2image,将 mkyaffs2image 拷贝到 /usr/bin 目录下即可

 (PS:自己生成的mkyaffs2image需要修改代码才能使用)

将生成的 fs_new.yaffs2 烧写到板子上,通过内核启动出现如下错误:

 4),修改移植最新yaffs2文件系统带来的错误(参考别人)

通过查找资料了解到可能是内存越界,我回去看了一下mkae uImge编译过程输出的信息,发现有几个warning,出现在yaffs_vfs.c和yaffs_guts.c这两个文件里。

到yaffs_vfs.c出现warning的行去,发现果然是yaffs_getxattr()这个函数的问题。文件中函数的定义是这样的:

看来是根据YAFFS_NEW_XATTR这个宏去分支,于是搜索这个宏:

看来它是根据内核版本来定义的:内核版本大于等于4.8.0时,这个宏为1,否则为0。

从上面可以看出,这个宏是被定义了的。也就是说对于yaffs_getxattr()这个函数的定义,是不会选择“#else”这个分支的,即它被定义为:

static int yaffs_setxattr(struct dentry *dentry, struct inode *inode, const char *name, const void *value, size_t size, int flags)

在这个文件中,函数的指针被传给了inode_operations 结构体的getxattr成员:

但是,这个成员在3.19内核的fs,h头文件中的原型却是:

ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);

也就是说,前文所讲的对于yaffs_getxattr()的定义,“#else”这个分支才是和3.19内核相符合的。这也是为什么warnimng中会出现“incompatible pointer types”这样的信息的原因。

要使用这个分支,我们只需要简单地做一下修改即可。

原文:#ifdef YAFFS_NEW_XATTR

改为:#if (YAFFS_NEW_XATTR > 0)

这样的话,对于3.19内核的情况(版本号小于4.8.0),YAFFS_NEW_XATTR宏展开为0,不符合#if的条件,就进入#else了。

出现在yaffs_guts.c中的那个warning,是由于其中result这个变量没有初始化引起的。

虽然不影响正常使用,我还是做了简单的修改。

原文: int result;

改为:int result = YAFFS_FAIL;

做了修改之后,覆盖掉linux-3.19/fs/yaffs2目录下的这两个源文件,再次make uImage,编译正常通过,之前的warning都不存在了。在开发板启动新的uImage,这时候已经能够正常挂接NAND Flash上的根文件系统了。Debug完成。

 

5,内核打补丁

制作补丁之前,先保存 .config 文件,然后 make distclean 清除,具体命令如下:

cp .config  config_ok            //保存到config_ok文件
make distclean                  
cd ..
mv linux-3.19  linux-3.4.2_zhyy  //更改文件名
tar -xjf linux-3.19.tar.bz2             //解压需要比较的源文件
diff -urN linux-3.19 linux-3.19_zhyy > linux-3.19_zhyy.patch    //生成补丁文件linux-3.19_zhyy.patch

 

使用补丁命令:

cd linux-3.19
patch -p1 < ../linux-3.19_zhyy.patch

 

 

至此内核移植和根文件系统制作已经完成。。。