在linux-2.6.27以前,谈到Flash文件系统,大家很多时候多会想到cramfs、jffs2、yaffs2等文件系统。它们也都是基于文件系统+mtd+flash设备的架构。linux-2.6.27后,内核加入了一种新型的flash文件系统UBI(Unsorted Block Images)。这里简单介绍下UBI文件系统加入的原因,及使用方法。我也是刚接触到这个文件系统,可能有理解不对的地方,也请指正。
一、产生的背景
FLASH具有的“先擦除再写入”、坏块、“有限的读写次数”等特性,目前管理FLASH的方法主要有:
1、采用MTD+FTL/NFTL(flash 转换层/nand flash转换层)+ 传统文件系统,如:FAT、ext2等。FTL/NFTL的使用就是针对FLASH的特有属性,通过软件的方式来实现日志管理、坏块管理、损益均衡等技术。但实践证明,由于知识产权、效率等各方面因素导致本方案有一定的局限性。
2、采用硬件翻译层+传统文件系统的方案。这种方法被很多存储卡产品采用,如:SD卡、U盘等。这种方案对于一些产品来说,成本较高。
3、采用MTD+ FLASH专用文件系统,如JFFS1/2,YAFFS1/2等。它们大大提高了FLASH的管理能力,并被广泛应用。
JFFS2、YAFFS2等专用文件系统也存在着一些技术瓶颈,如:内存消耗大,对FLASH容量、文件系统大小、内容、访问模式等的线性依赖,损益均衡能力差或过渡损益等。在此背景下内核加入了UBI文件系统的支持。
二、用法
环境:omap3530处理器、 (128MByte 16 位NAND Flash) 、linnux-2.6.28内核
1、配置内核支持UBIFS
Device Drivers --->Memory Technology Device (MTD) support --->UBI - Unsorted block images --->Enable UBI
配置mtd支持UBI接口
File systems --->Miscellaneous filesystems --->UBIFS file system support
配置内核支持UBIFS文件系统
2、将一个MTD分区4挂载为UBIFS格式
● flash_eraseall /dev/mtd4 //擦除mtd4
● ubiattach /dev/ubi_ctrl -m 4 //和mtd4关联
● ubimkvol /dev/ubi0 -N rootfs -s 100MiB //设定volume 大小(不是固定值,可以用工具改变)及名称
● mount -t ubifs ubi0_0 /mnt/ubi或mount -t ubifs ubi0:rootfs /mnt/ubi
3、制作UBIFS文件系统
在制作UBI镜像时,需要首先确定以下几个参数:
MTD partition size; //对应的FLASH分区大小
flash physical eraseblock size; // FLASH物理擦除块大小
minimum flash input/output unit size; //最小的FLASH输入输出单元大小
for NAND flashes - sub-page size; //对于nand flash来说,子页大小
logical eraseblock size.//逻辑擦除块大小
参数可以由几种方式得到
1)如果使用的是2.6.30以后的内核,这些信息可以通过工具从内核获得,如:mtdinfo –u。
2)之前的内核可以通过以下方法:
● MTD partition size:从内核的分区表或cat /proc/mtd获得
● flash physical eraseblock size:从flash芯片手册中可以得到FLASH物理擦除块大小,或cat /proc/mtd
● minimum flash input/output unit size:
1)nor flash:通常是1个字节
2)nand falsh:一个页面
● sub-page size:通过flash手册获得
● logical eraseblock size:对于有子页的NAND FLASH来说,等于“物理擦除块大小-1页的大小”
3)也可以通过ubi和mtd连接时的产生的信息获取,如:
#modprobe ubi mtd=4 //ubi作为模块加载
或
#ubiattach /dev/ubi_ctrl -m 4 //通过ubiattach关联MTD
UBI: attaching mtd4 to ubi0
UBI: physical eraseblock size: 131072 bytes (128 KiB)
UBI: logical eraseblock size: 129024 bytes
UBI: smallest flash I/O unit: 2048
UBI: sub-page size: 512
UBI: VID header offset: 512 (aligned 512)
UBI: data offset: 2048
UBI: attached mtd4 to ubi0
更详细的解释参见http://www.linux-mtd.infradead.org/doc/ubi.html#L_overhead
#mkfs.ubifs -r rootfs -m 2048 -e 129024 -c 812 -o ubifs.img
#ubinize -o ubi.img -m 2048 -p 128KiB -s 512 /home/lht/omap3530/tools/ubinize.cfg
-r:制定文件内容的位置
-m:页面大小
-e:逻辑擦除块大小
-p:物理擦除块大小
-c:最大的逻辑擦除块数量
对我们这种情况,文件系统最多可以访问卷上的129024*812=100M空间
-s:最小的硬件输入输出页面大小,如:k9f1208为256(上下半页访问)
其中,ubinize.cfg的内容为:
[ubifs]
mode=ubi
image=ubifs.img
vol_id=0
vol_size=100MiB
vol_type=dynamic
vol_name=rootfs
vol_flags=autoresize
4、利用uboot烧写、启动UBIFS镜像
1)烧写UBIFS镜像
OMAP3 DevKit8000 # mmcinit
OMAP3 DevKit8000 # fatload mmc 0:1 81000000 ubi.img
reading ubi.img
12845056 bytes read
OMAP3 DevKit8000 # nand unlock
device 0 whole chip
nand_unlock: start: 00000000, length: 268435456!
NAND flash successfully unlocked
OMAP3 DevKit8000 # nand ecc sw
OMAP3 DevKit8000 # nand erase 680000 7980000
NAND erase: device 0 offset 0x680000, size 0x7980000
Erasing at 0x7fe0000 -- 100% complete.
OK
OMAP3 DevKit8000 # nand write.i 81000000 680000 $(filesize)
NAND write: device 0 offset 0x680000, size 0xc40000
Writing data at 0x12bf800 -- 100% complete.
12845056 bytes written: OK
烧写过程和烧写内核镜像的过程一致,所以UBI文件系统应该不像yaffs文件系统那样用到了nand的OOB区域。
2)设置UBIFS文件系统作为根文件系统启动的参数
OMAP3 DevKit8000 # setenv bootargs console=ttyS2,115200n8 ubi.mtd=4 root=ubi0:rootfs
rootfstype=ubifs video=omapfb:mode:4.3inch_LCD
OMAP3 DevKit8000 # setenv bootcmd nand read.i 80300000 280000 200000/;bootm 80300000
根文件系统的位置在MTD4上
系统启动时会打印出如下和UBI相关的信息:
Creating 5 MTD partitions on "omap2-nand":
0x00000000-0x00080000 : "X-Loader"
0x00080000-0x00260000 : "U-Boot"
0x00260000-0x00280000 : "U-Boot Env"
0x00280000-0x00680000 : "Kernel"
0x00680000-0x08000000 : "File System"
UBI: attaching mtd4 to ubi0
UBI: physical eraseblock size: 131072 bytes (128 KiB)
UBI: logical eraseblock size: 129024 bytes
UBI: smallest flash I/O unit: 2048
UBI: sub-page size: 512
UBI: VID header offset: 512 (aligned 512)
UBI: data offset: 2048
UBI: attached mtd4 to ubi0
UBI: MTD device name: "File System"
UBI: MTD device size: 121 MiB
UBI: number of good PEBs: 970
UBI: number of bad PEBs: 2
UBI: max. allowed volumes: 128
UBI: wear-leveling threshold: 4096
UBI: number of internal volumes: 1
UBI: number of user volumes: 1
UBI: available PEBs: 0
UBI: total number of reserved PEBs: 970
UBI: number of PEBs reserved for bad PEB handling: 9
UBI: max/mean erase counter: 2/0
setenv bootargs ubi.mtd=4 root=ubi0:rootfs rootfstype=ubifs console=ttyS0,115200 mem=64M
启动系统即可,如下是启动信息:
U-Boot 1.3.3 (May 5 2009 - 13:04:13)
DRAM: 64 MB
NAND: 256 MiB
In: serial
Out: serial
Err: serial
Hit any key to stop autoboot: 0
U-Boot$
U-Boot$ setenv bootargs ubi.mtd=4 root=ubi0:rootfs rootfstype=ubifs console=ttyS0,115200 mem=64M
U-Boot$ ru yboot
NAND read: device 0 offset 0x200000, size 0x1b5968
Reading data from 0x3b5800 -- 100% complete.
1792360 bytes read: OK
## Booting kernel from Legacy Image at 81000000 ...
Image Name: Linux-2.6.27.8
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1792296 Bytes = 1.7 MB
Load Address: 80008000
Entry Point: 80008000
Verifying Checksum ... OK
Loading Kernel Image ... OK
OK
Starting kernel ...
Uncompressing Linux..................................................................................... done, booting the kernel.
Linux version 2.6.27.8 ([email protected]) (gcc version 4.3.2 (crosstool-NG-1.3.1) ) #8 PREEMPT Fri Nov 6 05:59:13 CST 2009
CPU: ARM926EJ-S [41069264] revision 4 (ARMv5TEJ), cr=00053177
Machine: SmartARM3250 board with the LPC3250 Microcontroller
Memory policy: ECC disabled, Data cache writeback
CPU0: D VIVT write-back cache
CPU0: I cache: 32768 bytes, associativity 4, 32 byte lines, 256 sets
CPU0: D cache: 32768 bytes, associativity 4, 32 byte lines, 256 sets
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 16256
Kernel command line: ubi.mtd=4 root=ubi0:rootfs rootfstype=ubifs console=ttyS0,115200 mem=64M
PID hash table entries: 256 (order: 8, 1024 bytes)
Console: colour dummy device 80x30
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 64MB = 64MB total
Memory: 61096KB available (3416K code, 230K data, 112K init)
Calibrating delay loop... 103.83 BogoMIPS (lpj=519168)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
net_namespace: 288 bytes
NET: Registered protocol family 16
Invalid board descriptor!
LPC32XX DMA driver
SCSI subsystem initialized
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 2048 (order: 2, 16384 bytes)
TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
TCP: Hash tables configured (established 2048 bind 2048)
TCP reno registered
NET: Registered protocol family 1
NetWinder Floating Point Emulator V0.97 (double precision)
JFFS2 version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
yaffs Sep 5 2009 09:21:41 Installing.
msgmni has been set to 119
io scheduler noop registered
io scheduler anticipatory registered
io scheduler deadline registered
io scheduler cfq registered (default)
CLCD: ZHIYUAN LCD hardware, QVGA portrait display
Console: switching to colour frame buffer device 40x30
Serial: 8250/16550 driver4 ports, IRQ sharing disabled
serial8250.0: ttyS0 at MMIO 0x40090000 (irq = 9) is a 16550A
console [ttyS0] enabled
serial8250.0: ttyS1 at MMIO 0x40080000 (irq = 7) is a 16550A
serial8250.0: ttyS2 at MMIO 0x40088000 (irq = 8) is a 16550A
serial8250.0: ttyS3 at MMIO 0x40098000 (irq = 10) is a 16550A
lpc32xx_hsuart.0: ttyTX0 at MMIO 0x40014000 (irq = 26) is a lpc32xx_hsuart
lpc32xx_hsuart.0: ttyTX1 at MMIO 0x40018000 (irq = 25) is a lpc32xx_hsuart
lpc32xx_hsuart.0: ttyTX2 at MMIO 0x4001c000 (irq = 24) is a lpc32xx_hsuart
loop: module loaded
LPC32XX_mii_bus: probed
eth0: LPC32XX mac at 0x31060000 irq 29
eth0: attached PHY driver [Generic PHY] (mii_bus:phy_addr=0:00, irq=-1)
Uniform Multi-Platform E-IDE driver
ide0 at 0xc4866020-0xc486602e,0xc486602e on irq 86
Driver 'sd' needs updating - please use bus_type methods
NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit)
Scanning device for bad blocks
Bad eraseblock 0 at 0x00000000
Bad eraseblock 1 at 0x00020000
Bad eraseblock 2 at 0x00040000
Bad eraseblock 152 at 0x01300000
Bad eraseblock 571 at 0x04760000
Bad eraseblock 1594 at 0x0c740000
Creating 5 MTD partitions on "lpc32xx_nand":
0x00000000-0x00180000 : "smartarm3250-boot"
0x00180000-0x001c0000 : "smartarm3250-ubt-prms"
0x00200000-0x00600000 : "smartarm3250-kernel"
0x00600000-0x01600000 : "smartarm3250-safefs"
0x01600000-0x10000000 : "smartarm3250-rootfs"
UBI: attaching mtd4 to ubi0
UBI: physical eraseblock size: 131072 bytes (128 KiB)
UBI: logical eraseblock size: 129024 bytes
UBI: smallest flash I/O unit: 2048
UBI: sub-page size: 512
UBI: VID header offset: 512 (aligned 512)
UBI: data offset: 2048
UBI: attached mtd4 to ubi0
UBI: MTD device name: "smartarm3250-rootfs"
UBI: MTD device size: 234 MiB
UBI: number of good PEBs: 1870
UBI: number of bad PEBs: 2
UBI: max. allowed volumes: 128
UBI: wear-leveling threshold: 4096
UBI: number of internal volumes: 1
UBI: number of user volumes: 1
UBI: available PEBs: 0
UBI: total number of reserved PEBs: 1870
UBI: number of PEBs reserved for bad PEB handling: 18
UBI: max/mean erase counter: 2/1
UBI: background thread "ubi_bgt0d" started, PID 262
at25 spi0.0: 32 KByte at25256a eeprom, pagesize 64
mice: PS/2 mouse device common for all mice
input: LPC32xx Touchscreen as /class/input/input0
rtc-lpc32xx rtc-lpc32xx: rtc core: registered rtc-lpc32xx as rtc0
i2c /dev entries driver
PNX4008-WDT: PNX4008 Watchdog Timer: heartbeat 19 sec
mmci-pl18x: DMA buffer(10000 bytes), P:0x839e0000, V:0xffc1a000
mmc0: MMCI rev 0 cfg 00 at 0x0000000020098000 irq 15,13
Advanced Linux Sound Architecture Driver Version 1.0.17.
ASoC version 0.13.2
UDA1380 Audio Codec 0.6<3>i2c-adapter i2c-4: Master timed out. stat = 0000, cntrl = 0000. Resetting master...
ALSA device list:
No soundcards found.
TCP cubic registered
NET: Registered protocol family 17
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
ieee80211: 802.11 data/management/control stack, git-1.1.13
ieee80211: Copyright (C) 2004-2005 Intel Corporation <[email protected]>
VFP support v0.3: implementor 41 architecture 1 part 10 variant 9 rev 1
rtc-lpc32xx rtc-lpc32xx: setting system clock to 2033-04-20 18:46:57 UTC (1997635617)
UBIFS: mounted UBI device 0, volume 0, name "rootfs"
UBIFS: file system size: 237017088 bytes (231462 KiB, 226 MiB, 1837 LEBs)
UBIFS: journal size: 11870208 bytes (11592 KiB, 11 MiB, 92 LEBs)
UBIFS: default compressor: LZO
UBIFS: media format 4, latest format 4
VFS: Mounted root (ubifs filesystem).
Freeing init memory: 112K
UBIFS: background thread "ubifs_bgt0_0" started, PID 304
init started: BusyBox v1.11.2 ()
starting pid 306, tty '': '/etc/rc.d/rcS'
Mounting /proc and /sys
Starting the hotplug events dispatcher udevd
Synthesizing initial hotplug events
Setting the hostname to zlg
Mounting filesystems
mount: mounting usbfs on /proc/bus/usb failed: No such file or directory
Running sysctl
Setting up networking on loopback device:
Setting up networking on eth0:
Adding static route for default gateway to 192.168.7.1:
Setting nameserver to 192.168.7.1 in /etc/resolv.conf:
Starting inetd:
Starting the port mapper:
Starting the ssh server:
starting pid 605, tty '': '-/bin/sh'
[root@zlg /]#
[root@zlg /]# ls
bin etc linuxrc proc sys usr
boot home mnt root tmp var
dev lib opt sbin ubifs
[root@zlg /]# df
Filesystem 1k-blocks Used Available Use% Mounted on
rootfs 217224 68612 143552 32% /
ubi0:rootfs 217224 68612 143552 32% /
tmpfs 30636 24 30612 0% /dev
shm 30636 0 30636 0% /dev/shm
rwfs 512 0 512 0% /mnt/rwfs