八,裁剪linux3.19.9内核,制作jffs2和yaffs2根文件系统
文档时间: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 烧写到板子上:
tftp 30000000 fs_new.yaffs2 nand erase.part rootfs nand write.yaffs 30000000 4a0000 $filesize set bootargs console=ttySAC0,115200 root=/dev/mtdblock3 rootfstype=yaffs2 reset
通过内核启动出现如下错误:
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
至此内核移植和根文件系统制作已经完成。。。