客户嵌入式系统启动即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 和 页大小。
/面朝大海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/
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/