ubifs號稱性能比yaffs2 好,同時壓縮可讀寫,文件系統image體較小同時可寫。
1. uboot使能對UBIFS的支持
#define CONFIG_CMD_NAND
#define CONFIG_CMD_UBI
#define CONFIG_CMD_UBIFS
#define CONFIG_RBTREE
#define CONFIG_MTD_DEVICE
#define CONFIG_MTD_PARTITIONS
#define CONFIG_CMD_MTDPARTS
#define CONFIG_LZO
注:需要燒寫mkfs.ubifs結果時候需要打開,ubinize處理過的鏡像不需要打開ubi專有配置。
2. Kernel使能對UBIFS的支持
•Enabling UBI support on MTD devices.
Device Drivers --->
Memory Technology Device (MTD) support --->
Enable UBI - Unsorted block images --->
•Enabling UBIFS file-system support
File systems --->
Miscellaneous filesystems --->
UBIFS file system support
3. 下載和編譯MTD Utilities
3.1 下載 MTD Utilites
通過 git://git.infradead.org/mtd-utils.git 下載最新的 MTD-Utils 源代碼。
下載 3 個編譯所需的依賴庫
Zlib: http://zlib.net/
Lzo: http://www.oberhumer.com/opensource/lzo/download/
e2fsprogs: http://e2fsprogs.sourceforge.net/
在用戶目錄下建立/mtd, /mtd/install 目錄,將以上 4 個 source code 包拷貝到/mtd下,安裝如下步驟先編譯依賴包:
zlib
host$ tar xvf zlib-1.2.5.tar.gz
host$ cd zlib-1.2.5/
host$ ./configure --prefix=~/mtd/install
host$ make
host$ make install
host$ cd ..
lzo
host$ tar xvf lzo-2.06.tar.gz
host$ cd lzo-2.06/
host$ ./configure --build=i686-pc-linux --prefix=~/mtd/install
host$ make
host$ make install
host$ cd ..
e2fsprogs
host$ tar xvf e2fsprogs-1.42.tar.gz
host$ cd e2fsprogs-1.42/
host$ ./configure --build=i686-pc-linux --prefix=~/mtd/install
host$ make
host$ make install
host$ cd lib/uuid/
host$ make install
host$ cd ../../../
3.2 編譯 MTD Utilites:
在編譯 mtd-utils 之前,先修改 makfile 文件:
host$ vi Makefile
PREFIX = ~/mtd/install
ZLIBCPPFLAGS = -I$(PREFIX)/include
LZOCPPFLAGS = -I$(PREFIX)/include
ZLIBLDFLAGS = -L$(PREFIX)/lib
LZOLDFLAGS = -L$(PREFIX)/lib
LDFLAGS += $(ZLIBLDFLAGS) $(LZOLDFLAGS)
CFLAGS ?= -O2 -g $(ZLIBCPPFLAGS) $(LZOCPPFLAGS)
host$ vi common.mk
#PREFIX=/usr
然后依照如下指令編譯:
host$ WITHOUT_XATTR=1 make
host$ make install DESTDIR=~/mtd/install
host$ cd ..
制作 ubi 文件系統所用的工具在如下目錄下: ~/mtd/install/home/<username>/mtd/install/sbin/mkfs.ubifs ~/mtd/install/home/<username>/mtd/install/sbin/ubinize
注:可直接采用系統自帶的mkfs.ubifs和ubinize工具,若不存在可apt-get安裝。
4. ubifs制作
(1) mkfs.ubifs
制作UBIFS image
mkfs.ubifs -r system -m 2048 -e 126976 -c 1057 -x zlib -o system.ubifs
mkfs.ubifs -r rootfs -o rootfs.img -F -m 2048 -e 124KiB -c 40
-r:待制作的文件系統目錄。
-o:輸出的image名字 。
-F:使能“white-space-fixup”,如果是通過u-boot燒寫需要使能此功能。
-m:Nand Flash的最小讀寫單元,一般為page size。
-e:LEB size,說的是邏輯擦除塊大小,大家知道nand flash頁讀頁寫塊擦,一個設備多個塊,一個塊多個頁,一般也都是一個塊是64個頁,這樣算一下無論擦除塊大小就是2048*64=131072,-e的算法是物理擦除塊大小-2*頁大小,這里就是131072-2*2048=126976
-c說的是最大邏輯塊數量,這個很重要,不能大也不能小,太小也要大於image大小,太大mount有問題。計算起點是分區的物理塊數量,比如128MiB的mtd分區,物理塊數量是128MiB/2048/64 = 1024個,需要減去2個壞塊保留塊,減去1個wear-leveling塊,還要減去1個eba的塊,等等,比如最終的值是1022,注意,如果物理上這個分區有壞塊的話,kernel會掃描到的,這時候,我們計算的這個值就要減去壞塊數了,否則會有邏輯塊大於物理塊數的內核問題mount失敗,確切知道壞塊數是比較困難的,一般做法是做一個壞塊容忍數,比如20個,這樣我們再減去20個壞塊,不要擔心這個會浪費空間,ubinize的autoresize選項就是解決這個問題的。具體的這個值需要計算。!!!!
-x說的是壓縮方法,默認是lzo,還支持zlib,zlib壓縮率高些,但是lzo壓縮解壓速度快 。
(2) ubinize
根據UBIFS image制作ubi.img,這個ubi.img是通過u-boot直接燒寫到nand flash分區上的。
ubinize -o system.ubi -m 2048 -p 131072 ubinize.cfg
-o說的是輸出image
-m還是頁大小
-p是物理擦除塊大小
ubinize.cfg是volume配置文件,例子如下:
[ubifs] mode=ubi image=system.ubifs #說的是mkfs.ubifs的結果 vol_id=0 vol_size=100MiB #說的是volume大小,用-e和-c的值做乘法計算,一般不用寫,autoresize會自動根據mtd分區大小適應,默認值是image大小,寫了這個作用是幫助檢查image是否超過了分區限制,制作時候就提示,否則mount會出錯。-c的值是經過計算的最大值了,不過autoresize參數會自適應大小,不會浪費空間的。 vol_type=dynamic vol_alignment=1 vol_name=system #說的是分區名字 vol_flags=autoresize
5. ubifs燒寫
(1)mkfs.ubifs工具制作的結果,就是ubifs鏡像,不包含volume信息,需要用
nand erase.part system – 擦除分區
ubi part system - 激活分區
ubi create system - 創建分區
ubi write 84000000 system xxxxx - xxxxx表示鏡像實際大小
(2)ubi volume bin燒寫
mkfs.ubifs后,使用ubinize處理了ubifs的鏡像后,鏡像含有了volume信息,直接
nand write 84000000 system xxxxx - xxxxx表示鏡像實際大小
(3)示例
TI AM335x一份uboot下燒寫記錄:
可通過 u-boot 命令將生成的 ubi.img( 25M)燒寫到 NAND FLASH 分區上, 如下示例是將 ubi.img 先存儲到 SD 卡上,然后通過 u-boot 的 fatload 命令將其拷貝至內存中。
u-boot# mw.b 0x82000000 0xFF
u-boot# mmc rescan
u-boot# fatload mmc 0 0x82000000 ubi.img
u-boot# nand erase 0x00780000 0xF880000
u-boot# nand write 0x82000000 0x00780000 0x1E00000
6. linux啟動參數設置
在 U-boot 下設置啟動信息如下:
#setenv bootargs 'console=ttyO0,115200n8 noinitrd ip=off mem=256M
rootwait=1 rw ubi.mtd=7,2048 rootfstype=ubifs root=ubi0:rootfs
init=/init'
可在命令行參數中增加多個ubi設備,如ubi.mtd=2,ubi.mtd=1,這樣傳遞后,內核啟動后會做attach的操作,attach之后,/dev/下就建立好設備了。
7. ubifs mount
UBI character devices:
a) /dev/ubi0, /dev/ubi1, … – UBI devices: volume create, delete, re-size, and get device description operations
b) /dev/ubi0_0, /dev/ubi0_1, … - UBI volumes: read, write, update, and get volume description operations
Linux 系統中有關mtd和ubi的接口:
(1) cat /proc/mtd:可以看到當前系統的各個mtd情況;
(2) cat /proc/partitions: 分區信息,有上面的類似;
(3) cat /sys/class/ubi/ubi0/*:當前系統的ubi0情況
(4) ls /dev/*, 查看設備節點
假設我們想在mtdblock1上加載ubifs文件系統,步驟如下:
(1)./ubiformat /dev/mtd1 -----格式化mtdblock1
(2)./ubiattach /dev/ubi_ctrl -m 1 -----將mtdblock1與ubi建立連接,命令輸出如下:
[ 977.342492] UBI: attaching mtd1 to ubi2 [ 977.346417] UBI: physical eraseblock size: 131072 bytes (128 KiB) [ 977.352631] UBI: logical eraseblock size: 126976 bytes [ 977.357948] UBI: smallest flash I/O unit: 2048
UBI device number 2, total 2000 LEBs (253952000 bytes, 242.2 MiB), available 1976 LEBs (250904576 bytes, 239.3 MiB), LEB size 126976 bytes (124.0 KiB)
系統自動將mtd1關連到ubi2上,假設系統中已經存在ubi0, ubi1了。
(3) ls /sys/class/ubi/ -----可以看到該目錄下增加了一個ubi2的子目錄
(4) cat /sys/class/ubi/ubi2/dev -----可以得到該ubi2設備的主次設備號,如249:0
(5) cat /sys/class/ubi/ubi2/volumes_count -----結果為0,表示該ubi上沒有任何volume
(6) ls /dev/ubi* -----如果/dev中沒有ubi2, 則手工創建“mknod /dev/ubi2 c 249 0”
(7) ./ubimkvol /dev/ubi2 -s 100MiB -N my_ubi_vol -----在ubi2上創建一個volume
(8) ls /sys/class/ubi/ -----可以看到該目錄下增加一個ubi2_0的目錄,代表ubi2上的第一個volume,如果“cat /sys/class/ubi/ubi2_0/name”, 你可以得到“my_ubi_vol”,這就是(7)中的名字。
(9) cat /sys/class/ubi/ubi2_0/dev -----得到該volume的主次設備號,如249:1
(10) mknod /dev/ubi2_0 c 249 1 -----如果/dev中沒有ubi2_0, 則需要手工創建
(11) mount -t ubifs ubi2_0 /mnt -----將ubi2_0掛載到本地目錄 /mnt上,
(12) mount -----可以看到ubi2_0成功掛載在/mnt上。
linux源碼中Documentation/filesystems/ubifs.txt中含有ubifs mount的用法:
Mount options
=============
(*) == default.
bulk_read read more in one go to take advantage of flash media that read faster sequentially
no_bulk_read (*) do not bulk-read
no_chk_data_crc skip checking of CRCs on data nodes in order to
improve read performance. Use this option only
if the flash media is highly reliable. The effect
of this option is that corruption of the contents
of a file can go unnoticed.
chk_data_crc (*) do not skip checking CRCs on data nodes
compr=none override default compressor and set it to "none"
compr=lzo override default compressor and set it to "lzo"
compr=zlib override default compressor and set it to "zlib"
Quick usage instructions
========================
The UBI volume to mount is specified using "ubiX_Y" or "ubiX:NAME" syntax, where "X" is UBI device number, "Y" is UBI volume number, and "NAME" is UBI volume name.
Mount volume 0 on UBI device 0 to /mnt/ubifs:
$ mount -t ubifs ubi0_0 /mnt/ubifs
Mount "rootfs" volume of UBI device 0 to /mnt/ubifs ("rootfs" is volume name):
$ mount -t ubifs ubi0:rootfs /mnt/ubifs
The following is an example of the kernel boot arguments to attach mtd0 to UBI and mount volume "rootfs":
ubi.mtd=0 root=ubi0:rootfs rootfstype=ubifs
附:常見問題
(1) ubifs_check_node: bad CRC: calculated 0xca82b3d7, read 0x9be0e26
ubifs_check_node: bad node at LEB 51:45312
注意這個crc錯誤,說的錯誤並不是LED 0的問題,也就是說第一個邏輯塊沒問題,CRC是正確的,這個問題的一個解決辦法是要精確mkfs.ubifs時候的-c參數的值,不能太大了
(2)
[ 5.433349] UBIFS error (pid 71): ubifs_read_node: bad node type (150 but expected 1)
[ 5.434204] UBIFS error (pid 71): ubifs_read_node: bad node at LEB 524:4072, LEB mapping status 1
[ 5.435241] Not a node, first 24 bytes:
[ 5.435729] 00000000: 34 fb 21 ee 84 18 69 2d 60 b0 33 e6 74 f8 1c 15 da ca a1 c9 96 e3 ac 51 4.!...i-`.3.t..........Q
這個問題是,ubifs給nand驅動的buffer不一定是按照硬件對齊要求的,所以要驅動來判斷,dma等地址需要頁對齊等特性
(3) crc錯誤,但是LED 0:0
可能鏡像沒燒對,或者mtd-utils的版本和內核版本相差較遠
(4) 可以擦掉一個分區,並不需要非要燒寫image到那個分區,也可以直接mount的,這樣可以做實驗驗證ubi的性能,前提是kernel配置好了,mount正確了
(5) 如果是跟文件系統或者要手動mount,以下步驟供參考:
uboot下, mtd命令后,看到需要用ubifs的mtd分區的編號,比如
device nand0 <rda_nand>, # parts = 10
#: name size offset mask_flags
0: bootloader 0x00200000 0x00000000 0
1: boot 0x00800000 0x00800000 0
2: system 0x08000000 0x02000000 0
system分區mtd編號是2,命令如下:
nand erase.part system
命令行參數增加ubi.mtd=2,如果有多個,可以增加,如ubi.mtd=2,ubi.mtd=1,這樣傳遞后,內核啟動后會做attach的操作,類似android的init中的attach那樣,attach之后,/dev/下就建立好設備了,進入系統后用:內核控制台里,mount -t ubifs /dev/ubi0_0 /mnt 即可mount
參考:
http://www.cnblogs.com/linucos/p/3279381.html
Ubifs文件系統的制作和啟動—TI FAE