一、编写目的
UBIFS是针对nand设备而设计的一种新文件系统。针对JFFS2、YAFFS2等专用文件系统也存在着一些技术瓶颈,如:内存消耗大,对FLASH容量、文件系统大小、内容、访问模式等的线性依赖,损益均衡能力差或过渡损益等,由于采用了压缩方式,UBI文件系统占用的空间比yaffs要小,而且避免了nand flash中OOB数据的操作。在此背景下内核加入了UBI文件系统的支持。需要注意的是UBIFS对异常掉电的容忍性差,容易出现CRC错误。
本文档用于记录为Linux增UBIFS文件系统支持的操作过程,方便日后查阅和参考。使用的软硬件环境如下,其它平台的可参考本文档进行类似操作即可。
BOARD:AT91SAM9260EK(GH11)
CPU:AT91SAM9260
NAND:K9F1208U0C 64MB
LINUX:2.6.39
gcc:arm-linux-gcc 4.3.2
LINUX内核源码下载:http://pan.baidu.com/s/1o6LTNRW
二、UBIFS文件系统移植
1. 内核配置
2.6.27以后,ubifs被整合进内核树中,本文档所使用的2.6.39内核中已经包好UBIFS的相关代码,因此直接进行make menuconfig配置即可。
Device Drivers --->
<*> Memory Technology Device (MTD) support --->
<*> Enable UBI - Unsorted block images --->
File systems --->
[*] Miscellaneous filesystems --->
<*> UBIFS file system support
[*] Extended attributes support
[*] Advanced compression options
[*] LZO compression support
[*] ZLIB compression support
2. 挂载UBIFS分区至/mnt目录
a) 查看LINUX内核所支持的文件系统类型,由下图可看出内核已经支持UBIFS
# cat /proc/filesystems
b) 创建UBIFS相关设备节点(没有以下两个设备文件的则需要创建,可将命令加到/etc/init.d/rcS中,让其开机自动创建)
# mknod /dev/ubi_ctrl c 10 63
# mknod /dev/ubi0 c 253 0 //这个文件没有的
c) 格式化一空闲分区,用于挂载UBIFS(我这里使用mtd6分区,原本用于挂载usr目录的)
# flash_eraseall /dev/mtd6
d) 将mtd6分区关联到ubi上(ubiattach可以在mtd-utils工具/busybox中取得,我这里是使用busybox中的)
# ubiattach /dev/ubi_ctrl -m 6 //最后一个数据表示分区号
e) 设定volume 大小(不是固定值,可以用工具改变)及名称(ubimkvol可以在mtd-utils工具/busybox中取得,我这里是使用busybox中的)
结合上一步(d步)的打印信息可知,这个分区总共有56MiB的空间,有3608片PEB可用,其中要分出一小部分PEB以供UBI运行时使用(具体多少没研究),还剩大部分PEB用来存储数据。因此这里设置volume 大小为54MiB,使用全部56MiB会提示错误,如下图所示。
# ubimkvol /dev/ubi0 -N rootfs -s 54MiB
f) 挂载/卸载文件系统
# mount -t ubifs ubi0:rootfs /mnt
# umount /mnt //如果在/mnt目录里卸载,会提示Device busy
g) 重复挂载
如果系统重启了,只需要重新执行关联(d步)和挂载(f步)操作即可。如果系统没有重新,则只需要执行f步操作即可。
3. 制作UBIFS文件系统镜像
a) 下载较新版本的mtd-utils(旧版本没有ubi-utils)
官方:http://git.infradead.org/mtd-utils.git
网盘:http://pan.baidu.com/s/1gd3Rk11 (mtd-utils-1.5.0.tar.bz2)
如何编译mtd-utils-1.5.0这里就不作详细说明,直接解压后make即可,然后把生成的可执行文件(mkfs.ubifs)复制至/usr/bin中。这里需要注意一点的是,编译mtd-utils之前需要安装libacl-deve、lzo-devel、libuuid-devel,Cent OS可以使用yum来安装。
b) 使用mkfs.ubifs制作UBIFS镜像
# mkfs.ubifs -m 512 -c 3567 -e 15872 -r ./NFS -o fs_mini.uboot.ubifs
以上命令的含义为将./NFS文件夹制作为UBIFS文件系统镜像,输出的镜像名为fs_mini.uboot.ubifs,-m参数指定了最小的I/O操作的大小,也就是NAND FLASH一个page的大小,-e参数指定了逻辑擦除快的大小,-c指定了最大的逻辑块号。通过此命令制作的出的UBIFS文件系统镜像可在u-boot下使用ubi write命令烧写到NAND FLASH上。
命令的参数根据实际的NAND进行调整,可以在分区关联到ubi时的输出信息中获取参数(即ubiattach命令,上面d步),这里对主要的参数进行说明一下:
-m: 最小的I/O操作的大小(也就是NAND FLASH的一个page的大小)
-c : 最大逻辑擦除块的数量(文件系统总容量/逻辑擦除块大小)
我这个板子文件系统最多可以访问卷上的15872*3567=54M空间
-e : 逻辑擦除块的大小
-r : 要制作成镜像的根文件系统的路径
-o : 最终制作成的根文件镜像的文件名
c) 配置ubinize.cfg
在当前目录新建ubinize.cfg文件,并输入以下内容:
[ubifs] mode=ubi image=fs_mini.uboot.ubifs vol_id=0 vol_size=54MiB vol_type=dynamic vol_alignment=1 vol_name=rootfs vol_flags=autoresize |
d) 转换成FLASH烧写格式
# ubinize -o fs_mini.flash.ubifs -m 512 -p 16KiB -s 256 ubinize.cfg
使用ubinize命令可将使用mkfs.ubifs命令制作的UBIFS文件系统镜像转换成可直接在FLASH上烧写的格式(带有UBI文件系统镜像卷标)。通过此命令生成的ubi.img可直接使用NAND FLASH的烧写命令烧写到FLASH上。
命令的参数根据实际的NAND进行调整,可以在分区关联到ubi时的输出信息中获取参数(即ubiattach命令,上面d步),这里对主要的参数进行说明一下:
-o : 最终制作成的根文件镜像的文件名
-m: 页面大小
-p: 物理擦除块大小
-s: 最小的硬件输入输出页面大小,如:k9f1208为256(上下半页访问)
e) 测试镜像是否能成功挂载
# flash_eraseall /dev/mtd6
# nandwrite -a -p /dev/mtd6 ./fs_mini.flash.ubifs
# ubiattach /dev/ubi_ctrl -m 6
# mount -t ubifs ubi0:rootfs /mnt //如果这步不成功,可参考前面的方法
到这里,已经可以知道制作的UBIFS镜像可以正常启动,并已把镜像通过MTD的FLASH工具烧写到NAND FLASH中(linux mtd6分区),现在可以修改Linux启动参数,让其挂载此分区为rootfs。也可以通过ATMEL提供的烧写工具SAM-BA将镜像烧写到0x007a0000地址。
# setenv bootargs 'mem=64M console=ttyS0,115200 mac=00:60:6E:42:BA:80 ubi.mtd=6 root=ubi0_0 rootfstype=ubifs ip=192.168.2.123:192.168.2.222:192.168.2.1:255.255.255.0:::eth0:off '