使用Ubuntu挂载解析ubi文件与使用mkfs.ubifs、ubinize制作ubi文件

一、应用背景

客户嵌入式系统启动即Crash,由于特殊原因没有打开抓取dump的功能,所以无法知晓客户系统Crash的原因。但基本确认是客户在文件系统中添加自己的应用程序启动后导致的,我们拿到故障机后导出rootfs分区对应ubi文件,需要将其挂载,然后排查核心文件是否被修改或者损坏或者其他原因导致Crash(因为原嵌入式系统挂载即Crash,我们需要使用Ubuntu挂载,然后排查挂载文件)。

UBI文件系统不能直接挂载,而是要用 nandsim 模拟出一个 mtd 设备,而且这个 mtd 设备要与 ubi 镜像的参数保存一致,否则后面的挂载会失败。
/面朝大海0902/

二、具体操作步骤

环境要求:Linux内核2.6及以上,本次操作使用环境Ubuntu 14.04。

1、载入mtd模块
modprobe mtdblock

2、载入ubi模块
modprobe ubi

3、载入nandsim来模拟nand设备
modprobe nandsim first_id_byte=0x2c second_id_byte=0xf1 third_id_byte=0x80 fourth_id_byte=0x95
// disk size=128MB, page size=2048 bytes,block size=128KB
nandsim 后面跟的 4 个参数是 nand flash 芯片的 ID,前三个参数为厂商ID、芯片ID等不太关键的参数,而第 4 个参数决定了生成的 mtd 设备的 PEB 和 页大小。
使用Ubuntu挂载解析ubi文件与使用mkfs.ubifs、ubinize制作ubi文件_第1张图片
/面朝大海0902/

4、查询相关参数

root@ubuntu:~# cat /proc/mtd
dev:    size   erasesize  name
mtd0: 08000000 00020000 "NAND simulator partition 0"
root@ubuntu:~# mtdinfo /dev/mtd
mtd0       mtd0ro     mtdblock0  
root@ubuntu:~# mtdinfo /dev/mtd0
mtd0
Name:                           NAND simulator partition 0
Type:                           nand
Eraseblock size:                131072 bytes, 128.0 KiB
Amount of eraseblocks:          1024 (134217728 bytes, 128.0 MiB)
Minimum input/output unit size: 2048 bytes
Sub-page size:                  512 bytes
OOB size:                       64 bytes
Character device major/minor:   90:0
Bad blocks are allowed:         true
Device is writable:             true

5、将 ubi 与 /dev/mtd0 关联
modprobe ubi mtd=0

6、需要安装mtd-utils工具箱(ubuntu下 直接apt-get install mtd-utils)
apt install mtd-utils

7、格式化前先解绑定,有可能报错,忽略直接往下一步继续走
ubidetach /dev/ubi_ctrl -m 0

8、把rootfs.bin加载到mtd的块设备
ubiformat /dev/mtd0 -s 2048 -f /home/book/Desktop/rootfs.bin -O 2048
ubiformat用法说明如下:

Usage: ubiformat <MTD device node file name> [-s <bytes>] [-O <offs>] [-n]
			[-f <file>] [-S <bytes>] [-e <value>] [-x <num>] [-y] [-q] [-v] [-h] [-v]
			[--sub-page-size=<bytes>] [--vid-hdr-offset=<offs>] [--no-volume-table]
			[--flash-image=<file>] [--image-size=<bytes>] [--erase-counter=<value>]
			[--ubi-ver=<num>] [--yes] [--quiet] [--verbose] [--help] [--version]

Example 1: ubiformat /dev/mtd0 -y - format MTD device number 0 and do
           not ask questions.
Example 2: ubiformat /dev/mtd0 -q -e 0 - format MTD device number 0,
           be quiet and force erase counter value 0.

-s, --sub-page-size=<bytes>  minimum input/output unit used for UBI
                             headers, e.g. sub-page size in case of NAND
                             flash (equivalent to the minimum input/output
                             unit size by default)
-O, --vid-hdr-offset=<offs>  offset if the VID header from start of the
                             physical eraseblock (default is the next
                             minimum I/O unit or sub-page after the EC
                             header)
-n, --no-volume-table        only erase all eraseblock and preserve erase
                             counters, do not write empty volume table
-f, --flash-image=<file>     flash image file, or '-' for stdin
-S, --image-size=<bytes>     bytes in input, if not reading from file
-e, --erase-counter=<value>  use <value> as the erase counter value for all
                             eraseblocks
-x, --ubi-ver=<num>          UBI version number to put to EC headers
                             (default is 1)
-Q, --image-seq=<num>        32-bit UBI image sequence number to use
                             (by default a random number is picked)
-y, --yes                    assume the answer is "yes" for all question
                             this program would otherwise ask
-q, --quiet                  suppress progress percentage information
-v, --verbose                be verbose
-h, -?, --help               print help message
-V, --version                print program version

-O参数很重要,要结合实际情况默认不加的话offset为512,如果后面attach失败,可以调整这个-O参数
我们这里选择2048,但是系统有提示,第二个提示我加载的文件和我设置的文件偏移参数不对应,按照系统识别的参数进行,选择no。


ubiformat /dev/mtd0 -s 2048 -f /home/book/Desktop/rootfs.bin -O 2048
ubiformat: 512 eraseblocks have valid erase counter, mean value is 0
ubiformat: 512 corrupted erase counters
ubiformat: warning!: only 512 of 1024 eraseblocks have valid erase counter
ubiformat: mean erase counter 0 will be used for the rest of eraseblock
ubiformat: continue? (yes/no)  yes
ubiformat: use erase counter 0 for all eraseblocks
ubiformat: warning!: VID header and data offsets on flash are 512 and 2048, which is different to requested offsets 2048 and 4096
ubiformat: use new offsets 2048 and 4096? (yes/no)  no
ubiformat: use offsets 512 and 2048
ubiformat: flashing eraseblock 511 -- 100 % complete  
ubiformat: formatting eraseblock 1023 -- 100 % complete

/面朝大海0902/

9、将ubi模块与已载入了rootfs.bin的mtd模块关联
ubiattach /dev/ubi_ctrl -m 0
-m指定挂在在mtd0上
attach成功打印如下:

root@ubuntu:~# ubiattach /dev/ubi_ctrl -m 0
UBI device number 0, total 1024 LEBs (132120576 bytes, 126.0 MiB), available 505 LEBs (65157120 bytes, 62.1 MiB), LEB size 129024 bytes (126.0 KiB)

10、创建一个需要被挂载的目录
mkdir /mnt/loop

11、挂载该模块到指定目录
mount -t ubifs ubi0 /mnt/loop/
挂载成功后,进入文件系统查看如下:

root@ubuntu:/mnt/loop# ls
alipay  cus_data  etc     firmware  lib    proc      sys  var
bin     data      etc_ro  work      media  recovery  tmp
cache   dev       etc_rw  home      mnt    sbin      usr

可以看到这个是一个根文件系统的目录结构。
/面朝大海0902/

三、ubifs制作

1、制作UBIFS image

mkfs.ubifs -r rootfs -m 0x800 -e 129024 -c 511 -x zlib -o rootfs.imgbak

Examples:
Build file system from directory /opt/img, writting the result in the ubifs.img file
	mkfs.ubifs -m 512 -e 128KiB -c 100 -r /opt/img ubifs.img
The same, but writting directly to an UBI volume
	mkfs.ubifs -r /opt/img /dev/ubi0_0
Creating an empty UBIFS filesystem on an UBI volume
	mkfs.ubifs /dev/ubi0_0

Options:
-r, -d, --root=DIR       build file system from directory DIR
-m, --min-io-size=SIZE   minimum I/O unit size
-e, --leb-size=SIZE      logical erase block size
-c, --max-leb-cnt=COUNT  maximum logical erase block count
-o, --output=FILE        output to FILE
-j, --jrn-size=SIZE      journal size
-R, --reserved=SIZE      how much space should be reserved for the super-user
-x, --compr=TYPE         compression type - "lzo", "favor_lzo", "zlib" or
                         "none" (default: "lzo")
-X, --favor-percent      may only be used with favor LZO compression and defines
                         how many percent better zlib should compress to make
                         mkfs.ubifs use zlib instead of LZO (default 20%)
-f, --fanout=NUM         fanout NUM (default: 8)
-F, --space-fixup        file-system free space has to be fixed up on first mount
                         (requires kernel version 3.0 or greater)
-k, --keyhash=TYPE       key hash type - "r5" or "test" (default: "r5")
-p, --orph-lebs=COUNT    count of erase blocks for orphans (default: 1)
-D, --devtable=FILE      use device table FILE
-U, --squash-uids        squash owners making all files owned by root
-l, --log-lebs=COUNT     count of erase blocks for the log (used only for
                         debugging)
-v, --verbose            verbose operation
-V, --version            display version information
-g, --debug=LEVEL        display debug information (0 - none, 1 - statistics,
                         2 - files, 3 - more details)
-h, --help               display this help text

-r:待制作的文件系统目录。

-o:输出的image名字 。

-m:Nand Flash的最小读写单元,一般为page size。

-e:LEB size,说的是逻辑擦除块大小,大家知道nand flash页读页写块擦,一个设备多个块,一个块多个页,-e的算法是物理擦除块大小-2页大小,如果支持sub-page 减1页大小。这里有一段话可以参考:

UBI utilizes sub-pages to lessen flash space overhead. The overhead is less if NAND flash 
supports sub-pages (see here).Indeed, let's consider a NAND flash with 128KiB eraseblocks and 
2048-byte pages. If it does not have sub-pages, UBI puts the the VID header at physical 
offset 2048, so LEB size becomes 124KiB (128KiB minus one NAND page which stores the EC 
header and minus another NAND page which stores the VID header. In opposite, if the NAND 
flash does have sub-pages, UBI puts the VID header at physical offset 512 (the second sub-page), 
so LEB size becomes 126KiB (128KiB minus one NAND page which is used for storing both UBI headers). 
See this section for more information about where the UBI headers are stored.

-c:说的是最大逻辑块数量。计算起点是分区的物理块数量,比如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 ./ap_rootfs.img -m 0x800 -p 0x20000 -s 512 rootfs.cfg

Example: ubinize -o ubi.img -p 16KiB -m 512 -s 256 cfg.ini - create UBI image
         'ubi.img' as described by configuration file 'cfg.ini'

-o, --output=<file name>     output file name
-p, --peb-size=<bytes>       size of the physical eraseblock of the flash
                             this UBI image is created for in bytes,
                             kilobytes (KiB), or megabytes (MiB)
                             (mandatory parameter)
-m, --min-io-size=<bytes>    minimum input/output unit size of the flash
                             in bytes
-s, --sub-page-size=<bytes>  minimum input/output unit used for UBI
                             headers, e.g. sub-page size in case of NAND
                             flash (equivalent to the minimum input/output
                             unit size by default)
-O, --vid-hdr-offset=<num>   offset if the VID header from start of the
                             physical eraseblock (default is the next
                             minimum I/O unit or sub-page after the EC
                             header)
-e, --erase-counter=<num>    the erase counter value to put to EC headers
                             (default is 0)
-x, --ubi-ver=<num>          UBI version number to put to EC headers
                             (default is 1)
-Q, --image-seq=<num>        32-bit UBI image sequence number to use
                             (by default a random number is picked)
-v, --verbose                be verbose
-h, --help                   print help message
-V, --version                print program version

-o说的是输出image

-m还是页大小

-p是物理擦除块大小

rootfs.cfg是volume配置文件,可参考如下格式:

[ubifs]
mode=ubi
image=rootfs.imgbak
vol_id=0
vol_size=59776KiB
vol_type=dynamic
vol_name=rootfs
vol_flags=autoresize

关于UBI有一篇文章写的非常好,推荐一下:
UBI文件系统-----UBI文件系统概念、UBI文件系统开销、UBI文件系统使用方法
/面朝大海0902/

你可能感兴趣的:(Linux驱动,ubuntu,linux)