yaffs 文件系统移植



3.Yaffs 文件系统移植

 

 

当使用 linuette 现成提供的 zImage.yaffs 和 usr.yaffs 是不能正常启动桌面系统的,因为它们提供

的包含 yaffs 的测试内核,支持的 LCD 是 320*480,以及触摸板的驱动也没有修改,所以必须在原来的内 核源代码中移植 yaffs 文件系统,才能在支持 yaffs 系统的同时,任意修改内核代码部分,如 LCD 分辨率、 触摸板,以及将驱动编译进内核等。

移植调试思路:参照 mizi 提供的 yaffs(源码不公开)的使用,及输出信息为线索,一步步的使移植 的功能接近它。如:1> 启动时的分区信息(BON info、MTD partitions)2> /dev/mtd 和/dev/mtdblock  3>

/proc/filesystems 4> mount –t yaffs /dev/mtdblock/1 /usr

 

 

3.1 在 vivi 中进行分区

 

 

vivi>bon part 0 192k 1M 3M:M

注:最后面的 M 表示为 mtd 分区,下面的 flag 将为 00000001;当然也可以只分 3 个区。

viiv>bon part show

BON info. (4 partitions)


No: offset     size          flags


bad


---------------------------------------------

0: 0x00000000 0x00030000    00000000    0  192k

1: 0x00030000 0x000d0000    00000000    0  832k

2: 0x00100000 0x00200000    00000000    0    2M

3: 0x00300000 0x03cfc000    00000001    0   60M+1008k vivi>load flash vivi x

vivi>load flash kernel x vivi>load flash root x vivi>boot

……

NAND device: Manufacturer ID: 0xec, Chip ID: 0x76 (Samsung NAND 64MiB 3,3V)

 

 

bon0: 00000000-00030000 (00030000) 00000000 bon1: 00030000-00100000 (000d0000) 00000000 bon2: 00100000-00300000 (00200000) 00000000 bon3: 00300000-03ffc000 (03cfc000) 00000001

……

注意:也可以只分 3 个区:

vivi> bon part 0 192k 1M

 

 


3.2


修改 MTD 驱动的 NAND 分区


 

 

修改 kernel/drivers/mtd/nand/smc_s3c2410.c 文件中的 smc_partitions[],如下:

static struct mtd_partition smc_partitions[] = {

{

name:         "bon",


 

 

 

 

 

}, {


size:         0x04000000, offset:    0x0,

mask_flags:   MTD_WRITEABLE,     /*force read-only */


name:


"mtd",


size:         0x03cfc000, offset:   0x00300000,

}

};

另外在该文件开始部分的消除分区宏定义:

#undef CONFIG_MTD_SMC_S3C2410_SMDK_PARTITION 修改成:

#define CONFIG_MTD_SMC_S3C2410_SMDK_PARTITION

内核配置时选中 Memory Technology Devices (MTD) ---> NAND Flash Device Drivers ---> SMC  Device

Support 及下属所有项 重新编译内核,下载,启动。输出信息如下:

……

NAND device: Manufacture ID: 0xec, Chip ID: 0x76 (Samsung K9D1208V0M) Creating 2 MTD partitions on "Samsung K9D1208V0M":

0x00000000-0x04000000 : "bon"

0x00300000-0x03ffc000 : "mtd"

bon0: 00000000-00030000 (00030000) 00000000 bon1: 00030000-00100000 (000d0000) 00000000 bon2: 00100000-00300000 (00200000) 00000000 bon3: 00300000-03ffc000 (03cfc000) 00000001

……

#cat /proc/mtd


dev:    size


erasesize  name


mtd0: 04000000 00004000 "bon" mtd1: 03cfc000 00004000 "mtd"

#ls /dev/mtd

0    0ro  1    1ro

#ls /dev/mtdblock

0  1

 

 

3.3 移植 yaffs 源代码

 

 

从官网(http://www.aleph1.co.uk/cgi-bin/viewcvs.cgi/yaffs/)下载源码(yaffs.tar.gz)解压, 在kernel/fs/目录下新建yaffs目录,将源码(yaffs_fs.c、yaffs_guts.c、yaffs_mtdif.c、yaffs_ecc.c、devextras.h、yaffs_guts.h、yaffs_mtdif.h、yaffs_ecc.h、yaffsinterface.h、yportenv.h)复制到该 目录下,创建yaffs_config.h文件,加入源码中使用到的宏定义,如下:

#ifndef   YAFFS_CONFIG_H

#define   YAFFS_CONFIG_H

#define CONFIG_YAFFS_MTD_ENABLED


#define CONFIG_YAFFS_USE_OLD_MTD

#endif

在该目录下创建 Makefile 文件,内容如下: O_TARGET := yaffs.o

 

 

obj-y := yaffs_fs.o yaffs_guts.o yaffs_mtdif.o yaffs_ecc.o obj-m := $(O_TAGRET)

 

 

include $(TOPDIR)/Rules.make

在 fs 目录的 Makefile 文件中加入 yaffs 子目录,如下:

subdir-$(CONFIG_YAFFS_FS) += yaffs

在 fs 目录的 Config.in 文件中加入 YAFFS 选项,如下:

if [ “$CONFIG_MTD_SMC” = “y” ]; then

tristate ‘Yaffs filesystem on NAND’ CONFIG_YAFFS_FS

fi

注:if 的[ ]与字符间要用空隔隔开,否则 if 条件会始终不成立

内核配置时选中 File system ---> Yaffs filesystem on SMC,再重新编译,下载,启动。输出信息 如下:

#cat /proc/filesystems nodev rootfs

nodev bdev nodev proc nodev sockfs nodev tmpfs nodev shm nodev pipefs cramfs

nodev ramfs vfat

nodev devfs nodev nfs jffs2

nodev autofs nodev devpts yaffs

#mount -t yaffs /dev/mtdblock/1 /usr yaffs: dev is 7937 name is "1f:01"

#mkdir /usr/ccn

#ls /usr

ccn         lost+found

#df -h

Filesystem                Size      Used Available UseMounted on

/dev/bon/2                2.7M      2.7M         0 100/

tmpfs                    30.6M         0     30.6M   0/dev/shm


/dev/mtdblock/1          61.0M    100.0k     60.9M   0/usr

 

 

3.4 出现的问题

 

 

34在 smc_partitions[]中添加 MTD 分区不起作用,下:

……

NAND device: Manufacture ID: 0xec, Chip ID: 0x76 (Samsung K9D1208V0M)

bon0: 00000000-00030000 (00030000) 00000000 bon1: 00030000-00100000 (000d0000) 00000000 bon2: 00100000-00300000 (00200000) 00000000 bon3: 00300000-03ffc000 (03cfc000) 00000001

……

#ls /dev/mtd

0    0ro

#ls /dev/mtdblock

0

#cat /proc/mtd

dev:    size   erasesize  name

mtd0: 04000000 00004000 "Samsung K9D1208V0M"

原因是定义分区的 smc_partitions[]在 CONFIG_MTD_SMC_S3C2410_SMDK_PARTITION 宏定义内,而在该 文件的开始又消除该宏定义,因此必须将消除修改成定义,如:

#undef CONFIG_MTD_SMC_S3C2410_SMDK_PARTITION 修改成:

#define CONFIG_MTD_SMC_S3C2410_SMDK_PARTITION

34在 fs 目录的 Config.in 文件中加入 YAFFS 选项,但在内核配置中始终没有出现 File system

---> Yaffs filesystem on SMC 项。

原因:Config.in 中 if 语句的[ ]与字符间要用空隔隔开,否则 if 条件会始终不成立,如下:

if [ “$CONFIG_MTD_SMC” = “y” ]; then

tristate ‘Yaffs filesystem on NAND’ CONFIG_YAFFS_FS

fi

34将加入 yaffs 的内核下载目标板启动后,仍没有 yaffs 项,如下:

# cat /proc/filesystems nodev rootfs

nodev bdev nodev proc nodev sockfs nodev tmpfs nodev shm nodev pipefs cramfs

nodev ramfs vfat

nodev devfs nodev nfs


nodev autofs nodev devpts

#

在 yaffs_fs.c 文件的 init_yaffs_fs()函数的开始和注册文件系统语句前增加打印信息,如下:

static int   init init_yaffs_fs(void){

int error = 0;

yaffs_dev = yaffsram_dev = NULL;

printk(“init_yaffs_fs…….\n”);

printk(KERN_DEBUG "yaffs "   DATE   " "   TIME   " Initialisation\n");

......

#ifdef CONFIG_YAFFS_MTD_ENABLED

printk(“register yaffs filesystem………”); error = register_filesystem(&yaffs_fs_type); if (error){

#ifdef CONFIG_YAFFS_RAM_ENABLED

unregister_filesystem(&yaffs_ram_fs_type);

#endif //CONFIG_YAFFS_RAM_ENABLED

}

#endif // CONFIG_YAFFS_MTD_ENABLED

return error;

重新编译,下载,启动信息如下:

……

devfs: v1.10 (20020120) Richard Gooch (rgooch@atnf.csiro.au)

devfs: boot_options: 0x1 init_yaffs_fs...............

ttyS00 at I/O 0x50000000 (irq = 52) is a S3C2410 ttyS01 at I/O 0x50004000 (irq = 55) is a S3C2410

……

由上述信息中只有“init_yaffs_fs…….”而没有“register yaffs filesystem……”,说明系统调 用了 yaffs 初始化函数,但没有执行文件系统注册函数,所以在/proc/filesystems 中也就没有 yaffs 项。 必须增加CONFIG_YAFFS_MTD_ENABLED 的宏定义,才能使该部分的注册函数有效,故在文件开始前增加:

#defined CONFIG_YAFFS_MTD_ENABLED

或者在源码目录下创建 yaffs_config.h 文件,定义源码中所有的宏定义,再被其它源文件包含。 再次编译,下载,启动信息如下:

……

devfs: v1.10 (20020120) Richard Gooch (rgooch@atnf.csiro.au)

devfs: boot_options: 0x1 init_yaffs_fs............... register_filesystem...................

ttyS00 at I/O 0x50000000 (irq = 52) is a S3C2410 ttyS01 at I/O 0x50004000 (irq = 55) is a S3C2410

……

#cat /proc/filesystems


nodev rootfs nodev bdev nodev proc nodev sockfs nodev tmpfs nodev shm nodev pipefs cramfs

nodev ramfs vfat

nodev devfs nodev nfs nodev autofs nodev devpts yaffs

#

34包含 CONFIG_YAFFS_MTD_ENABLED 宏定义后,编译出现错误:

yaffs_mtdif.c:33 variable ‘yaffs_oobinfo’ has initializer but incomplete type yaffs_mtdif.c:34 unknow field ‘useecc’ specified in initializer

……

将 yaffs_mtdif.c 中的用 nand_oobinfo 定义的两个结构体屏蔽掉

345 #mount –t yaffs /dev/mtdblock/1 /usr 出错

当执行该命令时会调用 yaffs_fs.c 文件中的 yaffs_internal_read_super()函数,主要还是该函数及 子函数出现错误,可以用 printk 函数打印信息的方法跟踪解决。本错误是由于当时没有将 yaffs_mtdif.c 文件中的 nand_oobinfo 结构完成屏蔽,而只是屏蔽掉了编译时出现错误的 useecc,所以在调试时出现一 系列对未初始化指针操作等错误。所以如果仔细按照上述的移植步骤操作,应不会出现类似的错误。

346 #./mkyaffs /dev/mtd/1 usr.yaffs 出现下述错误:

argc 4 sh 0 optcnt 2

MEMSETOOBSEL:Inappropriate ioctl for device

 

 

打开 yaffs 源码包 utils 目录下的 mkyaffs.c 文件(mkyaffs 工具的源文件),可以看出是下例语句出

现了错误:

Oobsel = usemtdecc ? yaffs_oobinfo : yaffs_noeccinfo;

if (ioctl(fd, MEMSETOOBSEL, &oobsel) != 0){

perror (“MEMSETOOBSEL”);

close (fd);

exit (1);

}

该功能给/dev/mtd/1 设备传递写入 nand flash 的 ecc 信息(mtdchar.c 文件的 ioctl()函数),和上 面屏蔽掉的 yaffs_mtdif.c 文件中的 yaffs_oobinfo 等是同一功能。由于我们使用的 MTD 驱动比较旧,查 看/drivers/mtd/mtdchar.c 文件的ioctl()函数可知还不支持该功能。因此也必须将 mkyaffs.c 文件中的 该功能去掉再重新编译生成 mkyaffs。或者使用原来的 mkyaffs 工具,但不加-e 参数,如:

#./mkyaffs /dev/mtd/1 usr.yaffs

或直接修改该源文件去掉-e 功能。


347 mkyaffs 编译出错

在 Makefile 文件中的 MAKETOOLS = 处添加交叉编译工具路径,如: MAKETOOLS = /opt/host/armv4l/bin/armv4l-unknown-linux-

将#include <mtd/mtd-user.h>替换成#include <linux/mtd/mtd.h>;将 nand_oobinfo 两个结构屏蔽 掉;将 main 函数中的 struct nand_oobinfo oobsel;和问题 6 提到的与 MEMSETOOBSEL 相关的语句屏蔽掉。

最后编译生成目标文件 mkyaffs_noecc(为了与原来的 mkyaffs 区别加上_noecc 后缀)。

34系统启动后/proc 目录为空等问题,如下:

#df –h

Filesystem         size          Used Available Use% Mounted on df: /proc/mounts: No such file or directory

#ls /proc

而且,在宿主机上也不能用 ztelnet 登录,提示: [root@localhost root_dir]#ztelnet 192.168.1.7

Trying 192.168.1.7

telnet: Unable to connect to remote host: Connection refused

原因是在 vivi 中的 kernel command line 参数有错误,如下述系统启动时的信息中缺少 linuxrc 脚本: Kernel command line: console=ttyS0 root=/dev/bon/2

在 vivi 下应设置成:

vivi> param set linux_cmd_line “noinitrd root=/dev/bon/2 init=linuxrc console=ttyS0” 启动后信息如下:

Kernel command line: noinitrd root=/dev/bon/2 init=linuxrc console=ttyS0

另外,yaffs 文件系统在多次使用,没有可用空间时,也可能出现该现象,需在 vivi 中重新分区,再 下载内核、文件系统等解决。

34挂载 yaffs 文件系统时出现错误,如下:

#mount –t yaffs /dev/mtdblock/1 /usr

yaffs: Attempting MTD mount on 31.1, “if:01”

mout: Mounting /dev/mtdblock/1 on /usr failed: Not a directory

原因是在执行 mkyaffsimage 工具打包 yaffs 格式文件系统影像时,加入了 convert 参数,如 在 PC 机上:

[root@localhost root_dir]#./mkyaffsimage ./root_english ./root_english.yaffs convert

‘convert’ produce a big-endian image from a little-endian machine

在目标板上:

#./mkyaffs /dev/mtd/1 ./root_english.yaffs

…… OK

#mount –t yaffs /dev/mtdblock/1 /usr

yaffs: Attempting MTD mount on 31.1, “if:01”

mout: Mounting /dev/mtdblock/1 on /usr failed: Not a directory

只需将刚才的 MTD 设备重新用 yaffs 系统格式化就可以,如下:

#./mkyaffs /dev/mtd/1

……

Erasing block at 0x83cf8000

OK

#mount –t yaffs /dev/mtdblock/1 /usr


yaffs: Attempting MTD mount on 31.1, “if:01”

#

制作 yaffs 文件系统的镜像不应加 convert 参数,但又要满足参数大于 3 个,所以第四个参数只要不 为 convert 就可以,

PC 机如下:

[root@localhost root_dir]#./mkyaffsimage ./root_english ./root_english.yaffs c

下载到目标板后执行:

#./mkyaffs /dev/mtd/1 ./root_english.yaffs

…… OK

#mount –t yaffs /dev/mtdblock/1 /usr

yaffs: Attempting MTD mount on 31.1, “if:01”

#

 

 

3yaffs 初始化及执行过程的简单总结

 

 

Step 1: 先调用 yaffs_fs.c 文件中的 init_yaffs_fs()初始化函数,它负责 yaffs 文件系统的注册,

将 yaffs 添加到/proc/filesystems 中;启动信息:

……

devfs: v1.10 (20020120) Richard Gooch (rgooch@atnf.csiro.au)

devfs: boot_options: 0x1

init_yaffs_fs...............                   (需要在函数中加该打印信息)

register_filesystem...................

……

Step 2: 调用 drivers/mtd/nand/smc_s3c2410.c 文件的 smc_s3c2410_init()函数扫描及初始化 NAND Flash 设备及底层接口函数,和 mtd 分区;启动信息:

……

NAND device: Manufacture ID: 0xec, Chip ID: 0x76 (Samsung K9D1208V0M)


add_mtd_partitions...


(需要在函数中加该打印信息)


Creating 2 MTD partitions on "Samsung K9D1208V0M":

0x00000000-0x04000000 : "bon"

0x00300000-0x03ffc000 : "mtd"

……

Step : 执行 mount –t yaffs /dev/mtdblock/1 /usr 命令时,调用 yaffs_fs.c 文件中的

yaffs_internal_read_super()函数。执行信息:

# mount -t yaffs /dev/mtdblock/1 /usr yaffs_internal_read_super.................   (需要在函数中加该打印信息) yaffs: Attempting MTD mount on 31.1, "1f:01"

Step 4: 另外还有对 yaffs 文件系统下的读或写等等,都会调用 yaffs_fs.c 文件下的相应函数,再 调用 mtd 设备对应的 NAND Flash 接口函数等。


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值