IoT(八)ubi文件系统挂载&解包【转】
转自:http://www.gandalf.site/2019/01/iotubi.html
0x1 UBI文件系统简介
UBI文件系统是linux-2.6.27后内核新加入的flash文件系统,开发环境主机要求至少是在linux2.6.27后的内核,且已经有nandsim,ubi等相关模块。
UBI没有FLASH转换层(FTL,Flash Translation Layer),只能工作在裸的flash,因此它不能用于消费类FLASH如MMC, RS-MMC, eMMC, SD, mini-SD, micro-SD, CompactFlash, MemoryStick等,但UBI在嵌入式设备中被广泛使用。
UBI文件系统不能直接挂载,而是要用 nandsim 模拟出一个 mtd 设备,而且这个 mtd 设备要与 ubi 镜像的参数保存一致,否则后面的挂载会失败。
这些参数包括 mtd 设备的物理块擦除大小 (Physical Erase Block, PEB) 和 页大小 (Page Size)。
ubi 镜像有多个 PEB 组成,每个 PEB 包括以下三部分内容
[
UBI_EC_HDR
,UBI_VID_HDR
,DATA (LEB)
]这是 ubi 镜像的头部,从
ubi-header.h
中可以了解到这个头部各个字节的含义:ubi-header.h
struct ubi_ec_hdr {
uint32_t magic; //红色,#define UBI_EC_HDR_MAGIC 0x55424923
uint8_t version;
uint8_t padding1[3];
uint64_t ec; /* Warning: the current limit is 31-bit anyway! */
uint32_t vid_hdr_offset; //蓝色,偏移为0x800=2KB
uint32_t data_offset; //黄色,偏移为0x1000=4KB
uint8_t padding2[36];
uint32_t hdr_crc;
} __attribute__ ((packed));
通常
UBI_EC_HDR
和 UBI_VID_HDR
要么在每个 PEB 的头部各占一页大小,要么都在第一页。若第一种,则页大小为2KB;若第二种页大小为4KB。nand flash 常见的页大小是 512byte 和 2KB,4KB 比较少见,故先推测为2KB。通过检索
![](https://user-images.githubusercontent.com/11291711/50503590-f43b0880-0aa2-11e9-8cdd-965360a21d0d.png)
UBI_EC_HDR_MAGIC
即0x55424923
,可以确定本次镜像PEB大小为0x20000=128KB,那么 LEB (Logical Erase Block)
=PEB-data_offset=128-4=124KB![](https://user-images.githubusercontent.com/11291711/50503590-f43b0880-0aa2-11e9-8cdd-965360a21d0d.png)
0x2 挂载方式
UBI文件系统的挂载方式,可以参考Linux mtd使用文档
1,创建一个需要被挂在的目录
1,创建一个需要被挂在的目录
# mkdir /mnt/loop
2,载入mtd模块
# modprobe mtdblock
3,载入ubi模块(前提你的linux环境以支持ubi模块)
# modprobe ubi
4,载入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
重点阅读 Read ID 部分,nandsim 后面跟的 4 个参数是 nand flash 芯片的 ID,前三个参数为厂商ID、芯片ID等不太关键的参数,而第 4 个参数决定了生成的 mtd 设备的 PEB 和 页大小。
![](https://user-images.githubusercontent.com/11291711/50534424-48afb800-0b77-11e9-93b4-ce4b21df14df.png)
![](https://user-images.githubusercontent.com/11291711/50534424-48afb800-0b77-11e9-93b4-ce4b21df14df.png)
5,检查加入模块的环境
# cat /proc/mtd
dev: size erasesize name
mtd0: 08000000 00020000 "NAND simulator partition 0"
//即镜像大小size=128MB,PEB=erasesize=128KB
# ls -la /dev/mtd*
crw-rw---- 1 root root 90, 0 2013-08-17 20:02 /dev/mtd0
crw-rw---- 1 root root 90, 1 2013-08-17 20:02 /dev/mtd0ro
brw-rw---- 1 root disk 31, 0 2013-08-17 20:03 /dev/mtdblock0
# 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
6,将 ubi 与 /dev/mtd0 关联
# modprobe ubi mtd=0
7,把rootfs.ubi加载到mtd的块设备,在这里需要安装mtd-utils工具箱(ubuntu下 直接apt-get install mtd-utils)
# apt install mtd-utils
# ubidetach /dev/ubi_ctrl -m 0 // 格式化前先解绑定
# ubiformat /dev/mtd0 -s 2048 -f rootfs.ubi -O 2048
ubiformat: mtd0 (nand), size 134217728 bytes (128.0 MiB), 1024 eraseblocks of 131072 bytes (128.0 KiB), min. I/O size 2048 bytes
libscan: scanning eraseblock 1023 -- 100 % complete
ubiformat: 1024 eraseblocks are supposedly empty
...
ubiformat: flashing eraseblock 208 -- 100 % complete
ubiformat: formatting eraseblock 1023 -- 100 % complete
// 指令功能类似于`dd if=rootfs.ubi of=/dev/mtdblock0 bs=2048`
//-O参数用来指定VID header offset,默认是512,本次镜像从上文分析得知为2048
遇到的坑
- ubiformat: error!: file “rootfs.ubi” (size 27267072 bytes) is not multiple of eraseblock size (131072 bytes)
- 如果确定文件
rootfs.ubi
块大小正确,可以详细检查文件,如下图,某设备镜像就修改了最后一个块的位置,将之修改回正确地址0x1a00000(删掉前面0x12个FF) - 修改完成后继续ubiformat,此时提示最后一个修改的块CRC校验错误
- ubiformat: flashing eraseblock 208 — 100 % complete ubiformat: error!: bad CRC 0xa092c947, should be 0x350fcaaa
0x350fcaaa
是原始值,将之修改为提示的0xa092c947
即可ubiformat成功ubiformat: 208 eraseblocks have valid erase counter, mean value is 3 ubiformat: 1 eraseblocks are supposedly empty ubiformat: 815 corrupted erase counters ubiformat: warning!: only 208 of 1024 eraseblocks have valid erase counter ubiformat: erase counter 0 will be used for all eraseblocks ubiformat: note, arbitrary erase counter value may be specified using -e option ubiformat: continue? (y/N) y ubiformat: use erase counter 0 for all eraseblocks ubiformat: flashing eraseblock 208 -- 100 % complete ubiformat: formatting eraseblock 1023 -- 100 % complete
- 如果确定文件
8,将ubi模块与已载入了rootfs.ubi的mtd模块关联
# ubiattach /dev/ubi_ctrl -m 0 -O 2048
UBI device number 0, total 1024 LEBs (130023424 bytes, 124.0 MiB), available 1000 LEBs (126976000 bytes, 121.1 MiB), LEB size 126976 bytes (124.0 KiB)
-m指定挂在在mtd0上
-O参数用来指定VID header offset,默认是512,本次镜像从上文分析得知为2048
到这里,模块载入成功,从输出信息可以知道rootfs.ubi镜像大小为124MB、共1024个块,每个LEB (Logical Erase Block) 大小为124KB
9,创建ubi分卷
# ubimkvol /dev/ubi0 -N ubifs_0 -m
10,挂载该模块到指定目录就OK
# mount -t ubifs ubi0:ubifs_0 /mnt/loop/
# ls -ahl /mnt/loop/
总用量 4.0K
drwxr-xr-x 22 root root 1.5K 4月 17 2018 .
drwxr-xr-x 6 root root 4.0K 12月 29 02:51 ..
drwxr-xr-x 2 root root 7.7K 4月 17 2018 bin
drwxr-xr-x 2 root root 160 4月 11 2018 boot
drwxr-xr-x 3 root root 224 4月 17 2018 data
drwxr-xr-x 2 root root 160 4月 11 2018 dev
drwxr-xr-x 24 root root 4.7K 4月 17 2018 etc
drwxr-xr-x 3 root root 224 4月 17 2018 home
drwxr-xr-x 6 root root 504 4月 11 2018 lib
drwxr-xr-x 5 root root 5.0K 4月 11 2018 lib64
drwxr-xr-x 2 root root 160 4月 11 2018 media
drwxr-xr-x 2 root root 160 4月 11 2018 mnt
drwxr-xr-x 2 root root 160 4月 11 2018 proc
drwxr-xr-x 2 root root 160 4月 11 2018 run
drwxr-xr-x 2 root root 4.1K 4月 17 2018 sbin
drwxr-xr-x 2 root root 160 4月 11 2018 sys
drwxr-xr-x 3 root root 224 4月 17 2018 temp
drwxr-xr-x 7 root root 504 4月 17 2018 test
drwxrwxrwt 2 root root 160 4月 11 2018 tmp
drwxr-xr-x 11 root root 736 4月 17 2018 usr
drwxr-xr-x 8 root root 808 4月 17 2018 var
drwxr-xr-x 3 root root 232 4月 17 2018 vendor
遇到的坑
- mount: /mnt/loop: unknown filesystem type ‘ubifs’.
- mount之前先创建ubi分卷即可
11,解挂载&绑定
$ sudo umount /mnt/ubi
$ sudo ubidetach /dev/ubi_ctrl -m 0
查看内核错误信息
如果遇到其他错误可以通过
dmesg | tail -20
来查看内核错误信息0x3 ubi解包
上述通过挂载方式读取ubi文件的过程较为繁琐,其实已经有现成开源的解包工具可用。
0x31 ubi_reader
ubi_reader工具地址为:https://github.com/jrspruitt/ubi_reader
可以直接通过pip安装:
可以直接通过pip安装:
//安装依赖
$ sudo apt-get install liblzo2-dev
$ sudo pip install python-lzo
//安装ubi_reader
$ sudo pip install ubi_reader
ubi_reader工具提供了四个脚本:
ubireader_display_info //获取UBI信息以及布局块等信息
ubireader_extract_images //提取镜像
ubireader_extract_files //提取文件内容
bireader_utils_info //分析UBI镜像并创建shell脚本和UBI配置文件
ubi_reader工具的使用也很简单,可以不需要参数,如下提取镜像里面的文件,输出会保存到
./ubifs-root/
目录里:$ ubireader_extract_files rootfs.ubi
$ ls -ahl ./ubifs-root/1726319237/rootfs
total 0
drwxr-xr-x 22 nirva staff 704B Dec 29 18:26 .
drwxr-xr-x 3 nirva staff 96B Dec 29 18:26 ..
drwxr-xr-x 114 nirva staff 3.6K Apr 17 2018 bin
drwxr-xr-x 2 nirva staff 64B Apr 11 2018 boot
drwxr-xr-x 3 nirva staff 96B Apr 17 2018 data
drwxr-xr-x 2 nirva staff 64B Apr 11 2018 dev
drwxr-xr-x 69 nirva staff 2.2K Apr 17 2018 etc
drwxr-xr-x 3 nirva staff 96B Apr 17 2018 home
drwxr-xr-x 7 nirva staff 224B Apr 11 2018 lib
drwxr-xr-x 68 nirva staff 2.1K Apr 11 2018 lib64
drwxr-xr-x 2 nirva staff 64B Apr 11 2018 media
drwxr-xr-x 2 nirva staff 64B Apr 11 2018 mnt
drwxr-xr-x 2 nirva staff 64B Apr 11 2018 proc
drwxr-xr-x 2 nirva staff 64B Apr 11 2018 run
drwxr-xr-x 60 nirva staff 1.9K Apr 17 2018 sbin
drwxr-xr-x 2 nirva staff 64B Apr 11 2018 sys
drwxr-xr-x 3 nirva staff 96B Apr 17 2018 temp
drwxr-xr-x 7 nirva staff 224B Apr 17 2018 test
drwxr-xr-x 2 nirva staff 64B Apr 11 2018 tmp
drwxr-xr-x 11 nirva staff 352B Apr 17 2018 usr
drwxr-xr-x 12 nirva staff 384B Apr 17 2018 var
drwxr-xr-x 3 nirva staff 96B Apr 17 2018 vendor
遇到的坑
- ubi_reader工具对于ubi文件要求较为严格,必须补齐每一个块内容,如下当最后一个块内容没填充满,会提示块空间大于文件:
根据PEB块大小,补齐00即可,如下将该块(size=0x20000)用00填充满read Error: Block ends at 27394048 which is greater than file size 27267072 extract_blocks Fatal: PEB: 208: Bad Read Offset Request
0x32 ubidump
相对于ubi_reader,ubidump工具就更为简单,无需对齐块,应该是直接检索块头magic进行提取,该工具地址为:https://github.com/nlitsme/ubidump
ubidump工具只是一个python2的脚本,无需安装,但需要安装依赖:
ubidump工具只是一个python2的脚本,无需安装,但需要安装依赖:
$ sudo pip install python-lzo
$ sudo pip install crcmod
使用也比较简单:
//查看image.ubi镜像里面的某个文件内容
$ python ubidump.py -c /etc/passwd image.ubi
//显示image.ubi镜像内容
$ python ubidump.py -l image.ubi
//提取镜像,该指令会在指定目录下生成`rootfs`目录
$ python ubidump.py -s . image.ubi
$ ls -ahl ./rootfs
total 0
drwxr-xr-x 11 nirva staff 352B Dec 29 20:32 .
drwx------ 20 nirva staff 640B Dec 29 20:32 ..
drwxr-xr-x 53 nirva staff 1.7K Dec 29 20:32 bin
drwxr-xr-x 3 nirva staff 96B Dec 29 20:32 data
drwxr-xr-x 62 nirva staff 1.9K Dec 29 20:32 etc
drwxr-xr-x 5 nirva staff 160B Dec 29 20:32 lib
drwxr-xr-x 38 nirva staff 1.2K Dec 29 20:32 lib64
drwxr-xr-x 15 nirva staff 480B Dec 29 20:32 sbin
drwxr-xr-x 3 nirva staff 96B Dec 29 20:32 temp
drwxr-xr-x 8 nirva staff 256B Dec 29 20:32 usr
drwxr-xr-x 3 nirva staff 96B Dec 29 20:32 vendor
【作者】sky
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.