UBI- Unsorted Block Images

UBI简介

UBI全称Unsorted Block Images,是一种原始flash设备的卷管理系统。这个系统能在一个物理的flash设备上管理多个卷并且能在整个flash芯片上实现损耗均衡。

从某种意义上说,UBI和LVM(Logical Volume Manager)有点相似,LVM将逻辑扇区映射到物理扇区上面,UBI映射逻辑擦除块到物理擦除块。但是除了映射,UBI还实现了全局的损耗均衡和透明的I/O错误处理。

一个UBI卷就是一串连续的逻辑擦除块(LEBs)。每一个逻辑擦除块可以被映射到任何一个物理擦除块(PEB)上面。这个映射是由UBI管理,这种映射对用户是透明的,同时这种映射也是UBI实现全局的损耗均衡的基础。通过每一个物理擦除块记录的擦除计数,可以将数据从损耗严重的物理块转移到损耗较少的擦除块。

UBIFS简介

UBIFS 是诺基亚工程师在塞格德大学的帮助下开发的一种新的闪存文件系统。 在某种程度上,UBIFS 可以被视为 JFFS2 文件系统的下一代。

UBIFS工作在UBI卷之上,不能在MTD设备之上运行,也不能在block设备上运行,因为ubifs的设计就是raw flash设备之上的文件系统。

这里为了便于理解,提到了一点ubusfs的概念,本文将着重介绍ubi,ubifs不是本文的重点内容。

UBI和UBIFS的关系如下图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qgpD64ix-1655455233269)(https://note.youdao.com/yws/res/27349/8527018A5D714EA7A3FA01DD7E517BB8)]

UBI PEB 和 LEB

以W25N01GV这款NAND Flash为例 (size 128MB, page size 2048, block size 128K)

在这里插入图片描述

在这里插入图片描述
PEB: 物理擦除块,和NAND FLASH中的一个物理block是一一对应的,大小也是一致的。
LEB:逻辑擦除块,实际可用大小比PEB少2个page(第一个page用于储存EC头,第二个page用于储存VID 头),而且LEB和PEB的映射关系不确定。

UBI 主要功能

UBI的主要功能如下:

  • UBI 提供可以动态创建、删除或调整大小的卷;
  • UBI 在整个闪存设备上实现磨损均衡(您可能认为您在不断地写入/擦除UBI卷的同一个逻辑擦除块,但实际上UBI 会将其均衡分配到闪存芯片的所有物理擦除块);
  • UBI 透明地处理坏物理擦除块;
    • UBI会处理坏的擦除块,无需上层软件参与。 UBI 有一个保留的物理擦除块池,当一个物理擦除块变坏时,它会透明地用一个好的物理擦除块替换它。 UBI 将数据从新发现的坏物理擦除块移动到好的物理擦除块。 结果是 UBI 卷的用户不会注意到 I/O 错误,因为 UBI 会透明地处理它们。
  • UBI 通过清理将丢失数据的机会降至最低。
    • NAND 闪存容易受到读写操作中发生的位翻转错误的影响。位翻转由ECC校验和纠正,但它们可能会随着时间的推移累积并导致数据丢失。UBI通过将数据从具有位翻转的物理擦除块移动到其他物理擦除块来处理这个问题。这个过程称为scrub。 scrub工作在后台透明地完成,并且对上层隐藏。

UBI卷

一个UBI卷就是一串连续的逻辑擦除块(LEBs)。

UBI卷大小在创建卷时指定,但以后可能会更改(卷可动态调整大小)。UBI提供用户空间工具用于操作UBI卷。

UBI卷有两种类型:

  • 静态卷。 静态卷是只读的,其内容受CRC-32校验和保护。
  • 动态卷。动态卷是可读写的,上层(文件系统)负责确保数据完整性。

静态卷通常用于内核、initramfs 和 dtb。 较大的静态卷在打开时可能会损失部分性能,因为需要计算 CRC-32。

动态卷可以动态创建、删除、调整大小。内核、initramfs或dtb之外的其他镜像最好使用动态卷。

MTD分区和UBI卷的相同点:

  • 两者都由擦除块组成——在UBI卷的情况下是逻辑擦除块,在MTD分区的情况下是物理擦除块;
  • 两者都支持三种基本操作:读、写和擦除。

但与 MTD分区相比,UBI卷具有以下优点:

  • UBI实现了wear-leveling,用户完全不用关心这个,也就是说上层软件会更简单;
  • UBI处理坏的擦除块,这也使上层软件更简单;
  • UBI 卷可以是动态的,它们可以动态创建、删除或调整大小,而MTD分区总是静态的;
  • UBI 处理位翻转,这再次使上层软件更简单;
  • UBI提供了卷更新操作,该操作使检测中断的软件更新和恢复变得更容易;
  • UBI 提供原子逻辑擦除块更改操作,如果在操作期间发生不干净的重启,它允许更改逻辑擦除块的内容而不会丢失数据;这可能对上层软件非常有用(例如,对于文件系统);
  • UBI有一个un-map 操作,它只是从物理擦除块中取消映射一个逻辑擦除块,调度物理擦除块进行擦除,然后返回;这非常快,并且使上层软件免于实现自己的机制来延迟擦除(例如,JFFS2必须实现这样的机制)。

除此之外,UBI还提供了一个块设备,允许将常规的、面向块的文件系统挂载在UBI卷的顶部。这是可能的,因为UBI透明地处理坏块。

UBI headers

UBI在每个非坏物理擦除块的开头存储2个小的64 字节headers:

  • 包含物理擦除块(PEB)的擦除计数器和其他信息的擦除计数器头(EC header)
  • 卷标识符头(VID header),存储卷ID 和此PEB所属的逻辑擦除块 (LEB) 编号

这就是逻辑擦除块小于物理擦除块的原因——header占用一些闪存空间

所有 UBI header都受 CRC-32 校验和保护。请参阅linux内核中的drivers/mtd/ubi/ubi-media.h 文件以获取有关header内容的更多信息。

/* Erase counter header magic number (ASCII "UBI#") */
#define UBI_EC_HDR_MAGIC  0x55424923
/* Volume identifier header magic number (ASCII "UBI!") */
#define UBI_VID_HDR_MAGIC 0x55424921

struct ubi_ec_hdr {
	__be32  magic;// 固定值 UBI_EC_HDR_MAGIC  0x55424923
	__u8    version;// 支持当前UBI image的UBI发行版本 默认为 #define UBI_VERSION 1
	__u8    padding1[3];//保留数据,默认为0
	__be64  ec; /*擦除计数器,目前只使用了31bit,其余bit保留 */
	__be32  vid_hdr_offset;// vid 头所在的偏移地址
	__be32  data_offset;//存储用户数据的起始地址
	__be32  image_seq;//image 序列号
	__u8    padding2[32];//填充字节
	__be32  hdr_crc;// ubi_ec_hdr 的CRC校验和
} __packed;

struct ubi_vid_hdr {
	__be32  magic;// 固定值 UBI_VID_HDR_MAGIC 0x55424921
	__u8    version;// 支持当前UBI image的UBI发行版本 默认为 #define UBI_VERSION 1
	__u8    vol_type;// 卷类型 动态卷和静态卷
	__u8    copy_flag;//该逻辑擦除块是否从另一个物理擦除块复制过来的(出于损耗平衡的原因)
	__u8    compat;//当前卷的兼容性
	__be32  vol_id;//当前卷id
	__be32  lnum;//逻辑块擦除计数
	__u8    padding1[4];//填充字节
	__be32  data_size;//当前LEB包含多少字节的数据
	__be32  used_ebs;//当前卷已经使用的LEB数量
	__be32  data_pad;//该物理擦除块末尾有多少字节未被使用
	__be32  data_crc;//当前LEB存储数据的CRC校验和
	__u8    padding2[4];//填充字节
	__be64  sqnum;// 序列号
	__u8    padding3[12];//填充字节
	__be32  hdr_crc;// ubi_vid_hdr 的CRC校验和
} __packed;

在这里插入图片描述
在这里插入图片描述

当 UBI attach一个 MTD 设备时,它必须扫描这个MTD设备,读取所有header,检查 CRC-32 校验和,并将擦除计数器和逻辑到物理擦除块映射信息存储在 RAM 中。

在 UBI 擦除了一个 PEB 之后,它会增加擦除计数器的值并将其写入 EC header。这意味着 PEB 总是有一个有效的 EC header,除了擦除之后和写入 EC 头之前的一小段时间。如果在这短时间内发生意外重启,EC header会丢失或损坏。在这种情况下,UBI 在 MTD 设备扫描完成后立即写入一个带有平均擦除计数器的新 EC header。

当 UBI 将其与 LEB 关联时,将 VID header写入 PEB。让我们考虑一下在某些 UBI 操作期间header会发生什么。

  • LEB un-map操作只是将 LEB 从 PEB 中取消映射并调度 PEB 以进行擦除。当 PEB 被擦除时,EC 头被立即写入。未写入 VID header。

  • LEB map操作或对未映射LEB的写入操作使 UBI找到合适的 PEB 并将 VID 标头写入其中(EC header必须已经存在)。请注意,对已经映射的 LEB 的写入操作只是将数据直接写入 PEB,并且不会更改 UBI header。

UBI针对每个PEB需要维护两个header,因为它需要在不同的时间将不同的信息写入闪存:

  • 擦除一个 PEB 后,立即写入 EC header,从而最大限度地减少由于意外重启而丢失擦除计数器的可能性;
  • 当 UBI 将一个 PEB 与一个 LEB 相关联时,VID header被写入到 PEB。

当 EC header写入 PEB 时,UBI 还不知道卷 ID 也不知道该 PEB 将关联到的 LEB 编号。这就是为什么 UBI 需要做两个独立的写操作并且有两个独立的headers。

UBI headers 位置

EC 标头始终位于偏移量0的位置并占用 64 字节,VID header位于下一个可用的最小 I/O 单元或sub-page处,也占用 64 字节。 例如:

  • 对于具有 1 字节最小I/O单元的 NOR Flash,VID 标头位于偏移量64;
  • 在没有sub-page的 NAND Flash的情况下,VID header位于第二个 NAND page;
  • 对于具有sub-page的 NAND Flash,VID header位于第二个sub-page。

UBI volume table

卷表是一个闪存数据结构,其中包含有关此 UBI 设备上每个卷的信息。卷表是卷表记录的数组。每条记录都包含以下信息:

  • 卷大小;
  • 卷名;
  • 卷类型(动态或静态);
  • 卷对齐;
  • 更新标记(在启动更新时设置在卷上,并在成功完成时清除);
  • auto-resize标志;
  • 此记录的 CRC-32 校验和。

每条记录描述一个UBI 卷。卷表数组中的记录索引对应于它所描述的卷ID。即,UBI卷0由卷表中的记录 0描述,依此类推。卷表中的记录总数受 LEB 大小的限制,不能大于 128。这意味着 UBI 设备的卷不能超过 128 个。

每次创建、删除、调整大小、重命名或更新UBI卷时,都会更改相应的卷表记录。出于可靠性和断电容错的原因,UBI 维护了卷表的两个副本。

在内部,卷表位于特殊用途的UBI卷中,称为layout volume。该卷由 2个LEB 组成(LEB0,LEB1)- 每个卷表和副本各占一个。layout volume是“内部”UBI 卷,用户看不到也无法访问它。在读取或写入layout volume时,UBI 使用与普通用户卷相同的机制。

UBI 在更新卷表记录时使用以下算法:

  • 准备一个包含新卷表内容的内存缓冲区。
  • 取消映射layout volume的 LEB0。
  • 将新卷表写入 LEB0。
  • 取消映射layout volume的 LEB1。
  • 将新卷表写入 LEB1。
  • 刷新 UBI 工作队列以确保PEB对应于未映射的LEB被擦除。

attach MTD 设备时,UBI确保2个卷表副本是等效的。如果它们不相等,可能是由于不干净的重启导致,UBI 从 LEB0 中选择一个并将其复制到布局卷的 LEB1(因为根据上面指定的算法,LEB0 是最先更新的,因此被认为拥有最新的信息)。如果其中一个卷表副本损坏,UBI 会从另一个卷表副本中恢复它。

FLASH 最小I/O单元

UBI 使用闪存的抽象模型。简而言之,从 UBI 的角度来看,闪存(或 MTD 设备)由擦除块组成,这些擦除块可能是好的也可能是坏的。每个好的擦除块都可以被读取、写入或擦除。好的擦除块也可能被标记为坏的。

闪存读取和写入只能以最小输入/输出单元大小的倍数进行,这取决于闪存类型。

  • NOR 闪存通常具有 1 个字节的最小 I/O 单元大小,因为 NOR 闪存通常允许读取和写入单个字节(实际上,甚至可以更改单个位)。
  • 一些 NOR 闪存可能具有其他最小 I/O 单元大小,例如对于 ECC 的 NOR 闪存,为 16 或 32 字节。
  • NAND 闪存的最小 I/O 大小通常为 512、2048 或 4096 字节,这与其page大小相对应。 NAND闪存在OOB区域存储每个page ECC代码,这意味着必须一次写入整个NAND页来计算ECC,并且必须一次读取整个NAND页来检查ECC。

最小I/O单元大小是MTD设备的一个非常重要的特性。它会影响很多事情,例如:

  • VID header的物理位置取决于最小 I/O 单元大小,这意味着 LEB 大小也取决于它;一般来说,最小 I/O 单元大小越大,LEB 大小越小,因此 UBI 闪存空间开销越大;
  • 所有对 LEB 的写入都应该与最小 I/O 单元大小对齐,并且应该是最小 I/O 单元大小的倍数;这不适用于读取,但请记住,在 MTD 级别上,所有读取无论如何都是以最小 I/O 单元大小的倍数完成的;这只是通过将读取的数据缓存起来,仅将用户实际请求的字节数复制到用户缓冲区,从用户的角度来看可以实现任意字节读取(最大读取数量为缓存区大小)。

UBI 闪存空间开销

UBI 将一些闪存空间用于自己的目的,从而减少了可供 UBI 用户使用的闪存空间量。 即:

  • 2个PEB用于存储卷表;
  • 1 PEB 保留用于磨损均衡目的;
  • 1个PEB是为原子LEB更改操作保留的;
  • 保留一些 PEB 用于不良的 PEB 处理; 这适用于 NAND 闪存,但不适用于 NOR 闪存; 保留的PEB数量是可配置的,默认等于每1024个区块20个区块;
  • UBI 将 EC 和 VID header存储在每个 PEB 的开头; 用于这些目的的字节数取决于闪存类型,如下所述。
  • W -闪存芯片上物理擦除块的总数(NB:整个芯片,不是MTD分区);
  • P - MTD 分区上的物理擦除块总数;
  • SP - 物理擦除块大小;
  • SL - 逻辑擦除块大小;
  • BB - MTD 分区上的坏块数;
  • BR - 为坏 PEB 处理保留的 PEB 数量(默认情况下,NAND 为 20 * W/1024,NOR 和其他没有坏 PEB 的闪存类型为 0)
  • B - MAX(BR,BB)
  • O - 与以字节为单位存储 EC 和 VID header相关的开销,即 O = SP - SL。

UBI 开销为 (B + 4) * SP + O * (P - B - 4),即用户无法访问此字节数。 O对于不同的Flash是不同的:

  • 在 NOR flash 的情况下,它具有 1 字节的最小 I/O 单元,O 是 128 字节;
  • 在没有sub-page的 NAND 闪存(例如 MLC NAND)的情况下,O 是 2 个 NAND page,即在 4KiB NAND page的情况下为 8KiB,在 512 字节 NAND page的情况下为 1KiB;
  • 对于具有sub-page的 NAND 闪存,UBI 优化其on-flash 布局并将 EC 和 VID header放在相同的 NAND page,但不同的sub-page中; 在这种情况下,O只是一个 NAND page;
  • 对于其他闪存,如果最小 I/O 单元大小大于或等于 64 字节,则开销应为 2 个最小 I/O 单元,如果最小I/O单元大小小于64字节,则开销应为2倍64字节并与最小I/O单元大小对齐。

注意:上面的公式将坏块计为 UBI 开销。 真正的 UBI 开销是:(B - BB + 4) * SP + O * (P - B - 4)。

UBI为坏块处理保留的擦除块 (only for NAND chips)

众所周知,NAND 芯片有一些被制造商标记为坏的物理擦除块。在 NAND 设备的生命周期中,可能会出现其他坏块。尽管如此,制造商通常会保证前几个物理擦除块没有坏,坏PEB的总数不会超过一定数量。例如,一个 256MiB(2048 个 128KiB PEB)的三星 OneNAND 芯片保证在其使用寿命期间不超过 40 个 128KiB PEB。这是 NAND 设备的一个非常常见的值:20/1024 PEB,大约是闪存大小的 2%。

这个 20/1024 的比率是UBI为每个UBI设备保留的默认块数。这意味着如果一个 4096 PEB NAND 上有 2 个 UBI 设备,每个UBI 设备将保留 80 个 PEB。这似乎是在浪费空间,但是,鉴于坏块可以出现在 NAND 闪存的任何位置,并且在整个设备上分布不均,这是更安全的方法。因此,与其在 NAND 闪存上使用多个UBI 设备,不如仅使用一个包含多个UBI卷的UBI设备更节省空间。

每 1024 个 PEB 保留 20 个PEB 的默认值是内核配置选项。对于每个 UBI 设备,可以通过内核参数或 ubiattach 参数(自内核 3.7 起)调整此值。

UBI标记坏块

本节与 NAND 闪存以及其他具有坏擦除块的闪存相关。 UBI 在以下两种情况下将物理擦除块标记为坏:

  • 擦除块写入操作失败,在这种情况下,UBI 将数据从该 PEB 移动到其他某个 PEB(数据恢复)并调度该 PEB 进行“折磨”;
  • 擦除操作因 EIO 错误而失败,在这种情况下,擦除块立即被标记为坏。

“折磨”是在后台进行的,目的是检测物理擦除块是否实际上是坏的。写入失败可能是由于多种原因之一发生的,包括驱动程序中的错误或文件系统等上层内容中的错误(例如,FS 错误地多次错误地写入同一个 NAND 页)。在“折磨” UBI 期间,UBI 会执行以下操作:

  • 擦除擦除块;
  • 读回它并确保它只包含 0xFF 字节;
  • 写测试模式字节;
  • 读回擦除块并检查模式;
  • 等等几种模式(0xA5、0x5A、0x00)。

如果擦除块在“酷刑”测试中幸存下来,则不会将其标记为坏块。然而,“酷刑”测试期间的位翻转是将擦除块标记为坏的一个很好的理由。有关详细信息,请参阅torture_peb() 函数。

UBI operations

to be continue

User-space tools

ubi tools官方仓库

http://git.infradead.org/mtd-utils.git
  • UBI相关tools如下:
tools说明备注
ubinfo提供有关在系统中找到的UBI设备和卷的信息
ubiattach链接MTD设备(原始Flash设备)到UBI并且创建相应的UBI设备
ubidetach将MTD设备与UBI设备分离(与ubiattach的作用相反);
ubimkvol在 UBI 设备上创建 UBI 卷
ubirmvol从 UBI 设备中删除 UBI 卷
ubiblock管理 UBI 卷的块接口
ubiupdatevol更新ubi卷,也可以用来清空ubi卷
ubicrc32计算与 UBI使用的初始种子相同的文件的 CRC-32校验和
ubinize生成ubi镜像注意是ubi镜像不是ubifs镜像
ubiformat格式化空flash,擦除flash并保留擦除计数器,将UBI镜像写入flash
mtdinfo查看系统中所有的mtd设备信息

ubinize

UBI镜像可以使用 ubinize 工具生成。 该工具在输入时获取配置文件并在输出时生成 UBI镜像。 输入配置文件用于描述需要生成的UBI镜像,且必须包含的所有的UBI卷。

Usage:ubinize [options] <ini-file>
options说明备注
-o, --output=输出到文件
-p, --peb-size=创建此UBI镜像的闪存的物理擦除块的大小,以字节、千字节 (KiB) 或兆字节 (MiB) 为单位(强制参数)
-m, --min-io-size=Flash的最小输入/输出单元大小(以字节为单位)
-s, --sub-page-size=用于 UBI headers的最小输入/输出单元,例如NAND flash 情况下的子页面大小(默认等于最小输入/输出单元大小)
-O, --vid-hdr-offset=偏移量,如果 VID header 从物理擦除块的开始(默认是 EC header之后的下一个最小 I/O 单元或子页面)
-e, --erase-counter=放入EC header的擦除计数器值(默认为 0)
-x, --ubi-ver=放入 EC header的UBI版本号(默认为 1)
-Q, --image-seq=要使用的32位UBI镜像序列号(默认选择随机数)

配置文件具有ini-file语法。

option说明备注
mode固定为ubi必填
image使用的ubifs镜像文件静态卷必须指定ubifs镜像文件
vol_id卷ID不填则自动分配
vol_size卷大小不填则自动分配一个能够容纳当前镜像的最小值
vol_type卷类型(static、dynamic)必填
vol_name卷名字必填
vol_flags卷标志位(autoresize,skip-check)选填

下面是一个配置文件示例:

[configuration-data-volume]
mode=ubi
image=config_data.img
vol_id=0
vol_size=512KiB
vol_type=static
vol_name=configuration

[rootfs-volume]
mode=ubi
image=rootfs.img
vol_id=1
vol_size=220MiB
vol_type=dynamic
vol_name=rootfs
vol_flags=autoresize

上述配置文件包含2个卷:

  • 静态配置卷大小为 512KiB,为其分配ID 0 并命名为configuration;卷的内容应取自config_data.img 文件;
  • 大小为 220MiB 的动态根文件系统卷,为其分配 ID 1 并命名为rootfs; 卷的内容应取自 rootfs.img文件; 这个卷还应该有auto-resize标志,这意味着这个卷的大小将在 UBI 第一次运行时被修改;UBI将通过提供可用的擦除块来使该卷变大;这在 NAND 闪存的情况下可能非常有用。

Volume flag auto-resize
当 UBI 映像在生产过程中被刷新时,应该为所有卷指定确切的大小(大小存储在 UBI 卷表中)。 然而,在嵌入式世界中,我们喜欢为根文件系统设置一个只读卷,为剩余的空间(日志、用户数据等)设置一个读/写卷。 如果根文件系统的大小是固定的,那么第二个文件系统的大小可能因产品而异(给定不同的闪存大小)。
这是自动调整大小标志的目的。 如果卷启用了autoresize标志,则在第一次运行 UBI 时,其大小将扩大以填充剩余的未使用空间。 调整卷大小后,UBI 删除自动调整大小标志,不再调整卷大小。 自动调整大小标志存储在volume table中,并且只有一个卷可以标记为自动调整大小。

Volume flag skip-check 为静态卷保留的flag

所以在上面的例子中,ubinize 基本上读取了 3 个输入文件:

  • config.ini 文件,描述生成的 ubi.img 文件应包含多少卷、它们的大小、名称等; 它还引用包含应该放入卷的数据的文件; 注意,如果卷应该是空的,就不要指定镜像文件;
  • 第一卷的 config_data.img 镜像文件;
  • 第二卷的 rootfs.img 镜像文件。

ubinize需要一个配置文件的原因是: 一个UBI 映像可能包含许多具有不同特征的UBI 卷,并且很难发明一个好的命令行界面来指定所有这些特征,因此使用了配置文件。

ubiattach

ubiattach工具用于链接MTD设备(raw Flash设备)到UBI并且创建相应的UBI设备。

Usage: ubiattach [<UBI control device node file name>]
	[-m <MTD device number>] [-d <UBI device number>] [-p <path to device>]
	[--mtdn=<MTD device number>] [--devn=<UBI device number>]
	[--dev-path=<path to device>]
	[--max-beb-per1024=<maximum bad block number per 1024 blocks>]
option说明选项
-d, --devn=分配给新创建的 UBI 设备的编号(如果未指定,则自动分配)
-p, --dev-path= 要附着的MTD设备节点的路径
-m, --mtdn=要附着的MTD设备号(例如/dev/mtdX X即MTD设备号)
-O, --vid-hdr-offsetVID header 偏移(不要指定这个除非你真的知道你在做什么,默认应该是最优的)
-b, --max-beb-per1024每1024个擦除块的最大预期坏块数。 对于大多数 NAND 设备,默认值是正确的。 允许的范围是 0-768,0 表示默认内核值。

如果<UBI control device node file name>未指定,就使用默认值/dev/ubi_ctrl

-p选项用于指定更具体的MTD设备节点,例如/dev/mtd19

-m选项和-p类似,也是指定MTD设备节点,但是更简洁,只需要MTD设备号即可

-b选项指定坏块冗余数量,但不是具体的数量。而是每1024个block需要多少个冗余块。

下面是一些使用实例:

Example 1: ubiattach -p /dev/mtd0 
        attach /dev/mtd0 to UBI

Example 2: ubiattach -m 0 
        attach MTD device 0 (mtd0) to UBI

Example 3: ubiattach -m 0 -d 3 
        attach MTD device 0 (mtd0) to UBI and create UBI device number 3 (ubi3)
           
Example 4: ubiattach -m 1 -b 25 
        attach /dev/mtd1 to UBI and reserve 25*C/1024 (如果FLASH共有4096个块, 则预留100个)

ubiattach的mtd设备可以是空设备,也可以是已经烧写了ubi镜像的设备;如果是前者,还需要手动创建卷之后才能使用。如果是后者,则会自动识别里面的ubi镜像信息,并根据ubi镜像的配置文件()自动创建卷,最后由用户手动挂载就可以使用了。

ubimkvol

ubimkvol工具用于在UBI设备上创建UBI卷

Usage: ubimkvol <UBI device node file name> [-h] [-a <alignment>] [-n <volume ID>] [-N <name>]
			[-s <bytes>] [-S <LEBs>] [-t <static|dynamic>] [-V] [-m] [-k]
			[--alignment=<alignment>][--vol_id=<volume ID>] [--name=<name>]
			[--size=<bytes>] [--lebs=<LEBs>] [--type=<static|dynamic>] [--help]
			[--version] [--maxavsize] [--skipcheck]

option说明备注
-a, --alignment=卷对齐(默认为1)
-n, --vol_id=UBI卷ID,如果不指定,卷ID会自动分配
-N, --name=卷名字必填
-s, --size=卷大小。卷大小以字节、千字节 (KiB) 或兆字节 (MiB) 为单位必填
-S, --lebs=在逻辑擦除块中给出卷大小的替代方法
-m, --maxavsize将卷大小设置为最大可用大小
-t, --type=<static/dynamic>卷类型(动态、静态),默认为动态
-k, --skipcheck跳过在卷打开时完成的 CRC 校验

下面是使用示例:

Example: ubimkvol /dev/ubi0 -s 20MiB -N config_data 
        create a 20 Megabytes volume named "config_data" on UBI device /dev/ubi0.

ubiformat

ubiformat工具 格式化MTD设备和烧写ubi镜像

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

option说明备注
-s, --sub-page-size=用于UBI header的最小输入/输出单元,例如 NAND flash 情况下的子页面大小(默认等于最小输入/输出单元大小)
-O, --vid-hdr-offset=偏移量,如果 VID header从物理擦除块的开始(默认是 EC 标头之后的下一个最小 I/O 单元或子页面)
-f, --flash-image=指定ubi镜像文件,如果为’-'表示从stdin读取
-S, --image-size=未指定具体的镜像文件时,从stdin读取的字节数
-e, --erase-counter=使用 作为所有擦除块的擦除计数器值
-x, --ubi-ver=放入EC header 的 UBI 版本号(默认为 1)
-Q, --image-seq=要使用的 32 位 UBI镜像序列号(默认选择随机数)
-y, --yes假设这个程序本来会问的所有问题的答案都是“yes”
-q, --quiet抑制进度百分比信息

ubiformat工具示例如下:

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

使用ubiformat擦除flash的好处是它可以保留擦除计数器。
另外ubiformat还可以用来烧写ubi镜像(镜像烧写后,需要使用ubiattach工具进行连接后再挂载使用)

ubiblock

UBI 允许在 UBI 卷上创建只读块设备,该卷适用于只读的、面向块的文件系统,例如 squashfs。
UBI允许在 UBI 卷上创建块设备,但有以下限制:

  • 只读操作。
  • 串行化 I/O 操作,但请记住 NAND 驱动内核也已经串行化了所有 I/O。
Usage: ubiblock [-c,-r] <UBI volume node file name>
option说明备注
-c, --create基于UBI卷创建块设备
-r, --remove删除基于UBI卷的块设备

必须基于UBI卷创建或者删除ubi块设备

$ubiblock -c /dev/ubi0_0
$ubiblock -r /dev/ubi0_0

ubi只读块设备被成功创建

# ls /dev/ubiblock* -l
brw-------    1 root     root      254,   0 Jun 16 15:19 /dev/ubiblock0_0

UBI使能

Linux 配置菜单中

"Device Drivers" 
    -> "Memory Technology Devices (MTD)" 
        -> "UBI - Unsorted block images"

参考

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐