转自:http://blog.chinaunix.net/uid-14114479-id-3150123.html
YAFFS2移植Linux2.6.39.2 成功(需要更改YAFFS2官方最新源代码)附上自己修改好的Linux2.6.39.2-yaffs2.tar.gz。
原以为Linux内核的YAFFS2文件系统移植很简单,网上一大片的,多的是,其实只要给Linux内核打个补丁就行了,对于Linux2.6.37及以前的内核,可能真的是很简单,就像上面说的,直接下载YAFFS2源码,然后通过执行源代码内的补丁就行了,但是对于Linux2.6.38及以后的内核,估计打完补丁也会编译不过,因为Linux2.6.38是Linux内核发展的一个分水岭,FS文件系统发生了变化,据官方说还加入了一个啥子神奇补丁,没仔细研究过,不清楚,但是文件系统的确是发生了变化,正是这种文件系统的变化,导致了YAFFS2移植遇到了问题,好了,夜已深了,也搞了几个小时了,眼睛都快打架了,野棉花扯多了,呵呵,还是步入正题吧,喜欢与人分享我的经验,呵呵,菜鸟一个,经验估计也谈不上,还是算愚见吧!
好了,本来是打算写点OK6410之Linux2.6.39.2触摸屏等驱动移植愚见的,心血来潮,放在NAND第四分区(MTDBLOCK3)的QT-YAFFS2文件系统无法启动,心里就怪痒痒的,既然老天让我们在此时相遇,那我也不再躲闪了(原本是放在后面再移植的,因为原以为打个补丁就行了),哎,说真的,遇到编译不过时,在网上找了好久,完全找不到解决办法,哎,算了,还是自己慢慢分析,解决吧。
移植方法:
第一步,我们需要YAFFS2的源码,如果大家有兴趣想了解YAFFS2文件系统的驱动原理的话可以直接去访问他们的官网,地址是
www.yaffs.net,上面说的很详细的,也有源码下载地址,怕大家进去后难找,直接贴出YAFFS2的最新源码地址吧,2011年6月28号的那个版本,
免费下载地址在
http://linux.linuxidc.com/
用户名与密码都是
www.linuxidc.com
具体下载目录在 /pub/2011/06/28/YAFFS2/
这个是目前最新的YAFFS2的源码了,不过虽然是最新源码已经被打过好多次补丁,但是对于Linux2.6.39.2的内核版本,还是不给力啊,编译依然无法通过,不是说过了吗,文件系统发生了变化。
第二步,将下载下来的YAFFS2最新源码 YAFFS2.tar.gz 放入你Linux的任意一个目录下,执行 tar zxvf YAFFS2.tar.gz 然后进入YAFFS2源码包,由于最新的源码再执行脚本 patch-ker.sh 时 有四个参数,可以追加:c,l,m,s,
./patch-ker.sh c/l m/s kernelpath
if c/l is c, then copy. If l then link
if m/s is m, then use multi version code. If s then use single version code
上面这段英文应该很好懂吧,简而言之,C 是复制文件,L是链接文件,M是多种,S是单个的,
那么在这里,我们只需执行 ./patch-ker.sh c m /your Linux2.6.39.2 kernel directory
执行完这条命令之后,你将会发现在Linux2.6.39.2/fs/下发现有了yaffs2目录了,并且里面也出现了好多文件
root@www.linuxidc.com:/SHARE/linux-2.6.39.2/fs/yaffs2# ls
Kconfig yaffs_linux.h yaffs_summary.c
Makefile yaffs_mtdif1.c yaffs_summary.h
yaffs_allocator.c yaffs_mtdif1.h yaffs_tagscompat.c
yaffs_allocator.h yaffs_mtdif2.c yaffs_tagscompat.h
yaffs_attribs.c yaffs_mtdif2.h yaffs_trace.h
yaffs_attribs.h yaffs_mtdif.c yaffs_verify.c
yaffs_bitmap.c yaffs_mtdif.h yaffs_verify.h
yaffs_bitmap.h yaffs_nameval.c yaffs_vfs.c
yaffs_checkptrw.c yaffs_nameval.h yaffs_yaffs1.c
yaffs_checkptrw.h yaffs_nand.c yaffs_yaffs1.h
yaffs_ecc.c yaffs_nand.h yaffs_yaffs2.c
yaffs_ecc.h yaffs_packedtags1.c yaffs_yaffs2.h
yaffs_getblockinfo.h yaffs_packedtags1.h yportenv.h
yaffs_guts.c yaffs_packedtags2.c
yaffs_guts.h yaffs_packedtags2.h
Kconfig yaffs_linux.h yaffs_summary.c
Makefile yaffs_mtdif1.c yaffs_summary.h
yaffs_allocator.c yaffs_mtdif1.h yaffs_tagscompat.c
yaffs_allocator.h yaffs_mtdif2.c yaffs_tagscompat.h
yaffs_attribs.c yaffs_mtdif2.h yaffs_trace.h
yaffs_attribs.h yaffs_mtdif.c yaffs_verify.c
yaffs_bitmap.c yaffs_mtdif.h yaffs_verify.h
yaffs_bitmap.h yaffs_nameval.c yaffs_vfs.c
yaffs_checkptrw.c yaffs_nameval.h yaffs_yaffs1.c
yaffs_checkptrw.h yaffs_nand.c yaffs_yaffs1.h
yaffs_ecc.c yaffs_nand.h yaffs_yaffs2.c
yaffs_ecc.h yaffs_packedtags1.c yaffs_yaffs2.h
yaffs_getblockinfo.h yaffs_packedtags1.h yportenv.h
yaffs_guts.c yaffs_packedtags2.c
yaffs_guts.h yaffs_packedtags2.h
说明这个补丁是打成功了,同时,你会发现,在fs目录下的Kconfig 和Makefile文件里也被相应的添加了加入yaffs2的支持信息,好了,到这一步,说明YAFFS2的补丁是打上了,但是由于是新版的LINUX2.6.39.2,所以导致编译无法通过,如果你不信的话,可以现在就编译试试看,会在生成YAFFS2.o时出错,而错误主要就是出现 在yaffs_vfs.c
这个文件上,
一个是
.get_sb ERROR问题,
还有就是get_sb_bdev ERROR问题。
根据自己的仔细分析,原来是新版的LINUX2.6.39.2文件系统发生变化,通过代码定位,
在LINUX2.6.39.2/includde/linux/fs.h上发现了一丝端倪,原来在新版的linux2.6.39.2里面,由于VFS发生变化,对于get_sb 以及get_sb_bdev这两个变量均为使用,
struct file_system_type {
const char *name;
const char *name;
int fs_flags;
struct dentry *(*mount) (struct file_system_type *, int,
const char *, void *);
void (*kill_sb) (struct super_block *);
struct dentry *(*mount) (struct file_system_type *, int,
const char *, void *);
void (*kill_sb) (struct super_block *);
。。。。。。
},在file_system_type这个结构体中我们根本就找不到 get_sb这个变量
通过对比linux2.6.36内核里面的fs.h,
struct file_system_type {
const char *name;
int fs_flags;
int (*get_sb) (struct file_system_type *, int,
const char *, void *, struct vfsmount *);
void (*kill_sb) (struct super_block *);
struct module *owner;
const char *name;
int fs_flags;
int (*get_sb) (struct file_system_type *, int,
const char *, void *, struct vfsmount *);
void (*kill_sb) (struct super_block *);
struct module *owner;
............
}
发现在结构体file_system_type是有get_sb这个变量定义的,
而在yaffs_vfs.c里面有两处是需要这个变量的,
第一处:
static struct file_system_type yaffs_fs_type = {
.owner = THIS_MODULE,
.name = "yaffs",
.get_sb = yaffs_read_super,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};
.owner = THIS_MODULE,
.name = "yaffs",
.get_sb = yaffs_read_super,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};
第二处:
static struct file_system_type yaffs2_fs_type = {
.owner = THIS_MODULE,
.name = "yaffs2",
.get_sb = yaffs2_read_super,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
}; 所以,我们需要更改yaffs_vfs.c里面的get_sb这个变量满足LINUX2.6.39.2的要求,通过比对,不难发现,其实LINUX2.6.39.2的fs.h里面的
.owner = THIS_MODULE,
.name = "yaffs2",
.get_sb = yaffs2_read_super,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
}; 所以,我们需要更改yaffs_vfs.c里面的get_sb这个变量满足LINUX2.6.39.2的要求,通过比对,不难发现,其实LINUX2.6.39.2的fs.h里面的
struct dentry *(*mount) (struct file_system_type *, int,
const char *, void *);这个函数与
const char *, void *);这个函数与
int (*get_sb) (struct file_system_type *, int,
const char *, void *, struct vfsmount *);很相似,
const char *, void *, struct vfsmount *);很相似,
于是 直接修改yaffs_vfs.c的
static struct file_system_type yaffs_fs_type
以及static struct file_system_type yaffs2_fs_type
两个结构体的get_sb变量,分别为:
.mount = yaffs_read_super,
.mount = yaffs2_read_super, 同理,对比,发现,用mount_bdev函数变量代替get_sb_bdev函数变量
return mount_bdev(fs, flags, dev_name, data,
yaffs_internal_read_super_mtd);
yaffs_internal_read_super_mtd);
return mount_bdev(fs, flags, dev_name, data,
yaffs2_internal_read_super_mtd);
yaffs2_internal_read_super_mtd);
第三步:
由于mount这个结构体函数少了struct vfsmount 这个参数,因此,我们还需要更改yaffs_vfs.c的两个位置,
通过阅读源代码不难发现
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
static int yaffs_internal_read_super_mtd(struct super_block *sb, void *data,
int silent)
{
return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL;
}
/*
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
static int yaffs_read_super(struct file_system_type *fs,
int flags, const char *dev_name,
void *data, struct vfsmount *mnt)
{
static int yaffs_internal_read_super_mtd(struct super_block *sb, void *data,
int silent)
{
return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL;
}
/*
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
static int yaffs_read_super(struct file_system_type *fs,
int flags, const char *dev_name,
void *data, struct vfsmount *mnt)
{
return get_sb_bdev(fs, flags, dev_name, data,
yaffs_internal_read_super_mtd, mnt);
}
#else
static struct super_block *yaffs_read_super(struct file_system_type *fs,
int flags, const char *dev_name,
void *data)
{
yaffs_internal_read_super_mtd, mnt);
}
#else
static struct super_block *yaffs_read_super(struct file_system_type *fs,
int flags, const char *dev_name,
void *data)
{
return get_sb_bdev(fs, flags, dev_name, data,
yaffs_internal_read_super_mtd);
}
#endif
*/
yaffs_internal_read_super_mtd);
}
#endif
*/
static struct super_block *yaffs_read_super(struct file_system_type *fs,
int flags, const char *dev_name,
void *data)
{
int flags, const char *dev_name,
void *data)
{
return mount_bdev(fs, flags, dev_name, data,
yaffs_internal_read_super_mtd);
}
yaffs_internal_read_super_mtd);
}
static struct file_system_type yaffs_fs_type = {
.owner = THIS_MODULE,
.name = "yaffs",
//.get_sb = yaffs_read_super,
.mount = yaffs_read_super,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};
#else
static struct super_block *yaffs_read_super(struct super_block *sb, void *data,
int silent)
{
return yaffs_internal_read_super(1, sb, data, silent);
}
.owner = THIS_MODULE,
.name = "yaffs",
//.get_sb = yaffs_read_super,
.mount = yaffs_read_super,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};
#else
static struct super_block *yaffs_read_super(struct super_block *sb, void *data,
int silent)
{
return yaffs_internal_read_super(1, sb, data, silent);
}
static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super,
FS_REQUIRES_DEV);
#endif
FS_REQUIRES_DEV);
#endif
在这段代码中,我发现,当LINXU内核版本大于2.6.17时与大于2.5.0而小于2.6.17时,采用的yaffs_read_super函数不一样,参数个数不同,而且类型也有所不同,一个是整形,一个是结构体,于是修改代码,红色为删掉不要的,蓝色为更改的,同理,第二处YAFFS2修改方法原理同上:直接贴出
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data,
int silent)
{
return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL;
}
/*
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
static int yaffs2_read_super(struct file_system_type *fs,
int flags, const char *dev_name, void *data,
struct vfsmount *mnt)
{
return get_sb_bdev(fs, flags, dev_name, data,
yaffs2_internal_read_super_mtd, mnt);
}
#else
static struct super_block *yaffs2_read_super(struct file_system_type *fs,
int flags, const char *dev_name,
void *data)
{
static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data,
int silent)
{
return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL;
}
/*
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
static int yaffs2_read_super(struct file_system_type *fs,
int flags, const char *dev_name, void *data,
struct vfsmount *mnt)
{
return get_sb_bdev(fs, flags, dev_name, data,
yaffs2_internal_read_super_mtd, mnt);
}
#else
static struct super_block *yaffs2_read_super(struct file_system_type *fs,
int flags, const char *dev_name,
void *data)
{
return get_sb_bdev(fs, flags, dev_name, data,
yaffs2_internal_read_super_mtd);
}
#endif
*/
static struct super_block *yaffs2_read_super(struct file_system_type *fs,
int flags, const char *dev_name,
void *data)
{
yaffs2_internal_read_super_mtd);
}
#endif
*/
static struct super_block *yaffs2_read_super(struct file_system_type *fs,
int flags, const char *dev_name,
void *data)
{
return mount_bdev(fs, flags, dev_name, data,
yaffs2_internal_read_super_mtd);
}
static struct file_system_type yaffs2_fs_type = {
.owner = THIS_MODULE,
.name = "yaffs2",
//.get_sb = yaffs2_read_super,
.mount = yaffs2_read_super,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};
#else
static struct super_block *yaffs2_read_super(struct super_block *sb,
void *data, int silent)
{
return yaffs_internal_read_super(2, sb, data, silent);
}
yaffs2_internal_read_super_mtd);
}
static struct file_system_type yaffs2_fs_type = {
.owner = THIS_MODULE,
.name = "yaffs2",
//.get_sb = yaffs2_read_super,
.mount = yaffs2_read_super,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};
#else
static struct super_block *yaffs2_read_super(struct super_block *sb,
void *data, int silent)
{
return yaffs_internal_read_super(2, sb, data, silent);
}
static DECLARE_FSTYPE(yaffs2_fs_type, "yaffs2", yaffs2_read_super,
FS_REQUIRES_DEV);
#endif 好了,经过这3步修改之后,编译通过,当然,还是会有告警信息打印,很正常,因为原来的get_sb_bdev函数是一个 INT型,而mount_bdev函数是一个 STRUCT结构体型,导致RETURN 指针类型不符的告警,无大碍。
FS_REQUIRES_DEV);
#endif 好了,经过这3步修改之后,编译通过,当然,还是会有告警信息打印,很正常,因为原来的get_sb_bdev函数是一个 INT型,而mount_bdev函数是一个 STRUCT结构体型,导致RETURN 指针类型不符的告警,无大碍。
运行很好,完全没问题,通过[root@FORLINX6410 /]# cat /proc/filesystems 打印信息:
nodev sockfs
nodev usbfs
nodev pipefs
nodev usbfs
nodev pipefs
nodev anon_inodefs
nodev rpc_pipefs
nodev devpts
ext3
ext2
cramfs
nodev ramfs
vfat
msdos
nodev nfs
nodev nfs4
nodev nfsd
ntfs
romfs
nodev fuse
fuseblk
nodev fusectl
yaffs
yaffs2
nodev mtd_inodefs
nodev rpc_pipefs
nodev devpts
ext3
ext2
cramfs
nodev ramfs
vfat
msdos
nodev nfs
nodev nfs4
nodev nfsd
ntfs
romfs
nodev fuse
fuseblk
nodev fusectl
yaffs
yaffs2
nodev mtd_inodefs
可见,这个修改方法还是很成功的 ,看到网上那么多的朋友都遇到LINUX2.6.38及以后版本的YAFFS2的文件系统移植问题,又没人提出解决方案,所以一解决问题就马上贴了出来,希望对你们有所帮助!!好了,该睡觉了啊,写的有点仓促,如果有地方没看明白,就留言吧。
最后还是附上我修改好的LINUX2.6.39.2的YAFFS2的包包吧,
免费下载地址在
http://linux.linuxidc.com/
用户名与密码都是
www.linuxidc.com
具体下载目录在 /pub/2011/06/28/YAFFS2/修改好的Linux2.6.39.2的YAFFS2的包
安装方法,在linux2.6.39.2/fs/ 下 mkdir yaffs2 然后解压,将其全部内容拷贝进去,并修改linux2.6.39.2/fs/ 下的Kconfig 在
source "fs/efs/Kconfig"与
source "fs/jffs2/Kconfig"之间添加source "fs/yaffs2/Kconfig",然后还需修改Makefile,在最后一行添加:
obj-$(CONFIG_YAFFS_FS) += yaffs2/,最后贴上我的MENUCONFIG吧:
<*> yaffs2 file system support
-*- 512 byte / page devices
-*- 512 byte / page devices
-*- 2048 byte (or larger) / page devices
[*] Autoselect yaffs2 format
[*] Autoselect yaffs2 format
[*] Enable yaffs2 xattr support