uboot支持ubi和ubifs遇到的问题

本文解决U-Boot环境下NAND闪存使用UBI格式化及分区过程中的常见错误,包括配置调整、命令参数修正及mkfs.ubifs使用技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

uboot version 2012.10

nand type:Micron MT29F16G08CBACA


一、执行ubi part kernel时报错-12

Creating 1 MTD partitions on "nand0":

0x000004200000-0x00001e200000 : "mtd=3"

UBI: attaching mtd1 to ubi0

UBI warning: io_init: EC and VID headers are in thesame minimal I/O unit, switch to read-only mode

UBI: physical eraseblock size: 1048576 bytes (1024KiB)

UBI: logical eraseblock size: 1044480 bytes

UBI: smallest flash I/O unit: 4096

UBI: VID header offset: 2048 (aligned 0)

UBI: data offset: 4096

UBI error: ubi_init: cannot attach mtd1

UBIerror: ubi_init: UBI error: cannot initialize UBI, error -12

UBI init error 12

Error, no UBI device/partition selected!

 

网上一般都是说将CONFIG_SYS_MALLOC_LEN,增大到1M(1024*1024)。但我修改后同样报错

找到源码中报错的地方(/drivers/mtd/ubi/build.cubi_attach_mtd_dev函数)

err = -ENOMEM;

ubi->peb_buf1 = vmalloc(ubi->peb_size);

if (!ubi->peb_buf1)

goto out_free;

 

ubi->peb_buf2 = vmalloc(ubi->peb_size);

if (!ubi->peb_buf2)

goto out_free;

malloc大小为ubi->peb_size,经过查找最终是在(/driver/mtd/nand/nand_base.cnand_get_flash_type函数)

/* Calc blocksize */

mtd->erasesize = (128 * 1024) <<

(((extid >> 1) & 0x04) | (extid &0x03));

实际该值就是物理擦出块大小,通过芯片ID获取芯片类型,查看手册

该值为1024KB,那么问题就来了,CONFIG_SYS_MALLOC_LEN设置成1M,现在一次malloc的大小也是1M,连续两次malloc就会报错了,所以当nand芯片的块大小大于等于1M时,CONFIG_SYS_MALLOC_LEN就应该相应增大,我设置成4M了


二、执行ubi part kernel时报错
Creating 1 MTD partitions on "nand0":
0x000004200000-0x00001e200000 : "mtd=3"
UBI: attaching mtd1 to ubi0
UBI warning: io_init: EC and VID headers are in the same minimal I/O unit, switch to read-only mode
UBI: physical eraseblock size: 1048576 bytes (1024 KiB)
UBI: logical eraseblock size: 1044480 bytes
UBI: smallest flash I/O unit: 4096
UBI: VID header offset: 2048 (aligned 0)
UBI: data offset: 4096
UBI: empty MTD device detected
UBI: create volume table (copy #1)
UBI error: ubi_io_sync_erase: read-only mode
UBI error: ubi_io_sync_erase: read-only mode
UBI error: ubi_io_sync_erase: read-only mode
UBI error: ubi_io_sync_erase: read-only mode
可以看到创建卷时提示ubi处于只读模式,同时注意到一个warning,找到源码位置(/drivers/mtd/ubi/build.c io_init函数)
/*
* It may happen that EC and VID headers are situated in one minimal
* I/O unit. In this case we can only accept this UBI image in
* read-only mode.
*/
if (ubi->vid_hdr_offset + UBI_VID_HDR_SIZE <= ubi->hdrs_min_io_size) {
ubi_warn("EC and VID headers are in the same minimal I/O unit, "
"switch to read-only mode");
ubi->ro_mode = 1;
}
经过打印
UBI_VID_HDR_SIZE = 64
ubi->vid_hdr_offset = 2048
ubi->hdrs_min_io_size = 4096
确实有问题,从nand手册上来看,最小的页为4k,所以hdrs_min_io_size应该没问题
而vid_hdr_offset就有点奇怪,最后找到这个值是由ubi part传进来的参数
修正命令
ubi part kernel -->ubi part kernel 4096

三、执行 ubifsmount kernel报错-19

UBIFS error (pid 0): ubifs_get_sb: cannot open"ubi:kernel1", error -19

UBIFS error (pid 0): ubifs_mount: Error readingsuperblock on volume 'ubi:kernel1' errno=-19!

这应该是制作kernel镜像时mkfs.ubifs参数的问题了(都是跟nand相关的参数)

再次介绍mkfs.ubifs的用法 

Usage: mkfs.ubifs [OPTIONS] target 

Make a UBIFS file system image from an existingdirectory tree 

Examples: 

Build file system from directory /opt/img, writtingthe 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 UBIvolume 

        mkfs.ubifs/dev/ubi0_0 

Options: 

-r, -d, --root=DIR              buildfile 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    maximumlogical erase block count最大逻辑可擦出块数目 

-o, --output=FILE       output to FILE输出文件名 

-j, --jrn-size=SIZE     journal size 

-R, --reserved=SIZE      howmuch 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 compressionand defines 

                                howmany percent better zlib should compress to make 

                                mkfs.ubifsuse zlib instead of LZO (default 20%) 

-f, --fanout=NUM         fanout NUM (default:8) 

-F, --space-fixup        file-system free space has tobe fixed up on first moun

                          (requireskernel version 3.0 or greater) 

-k, --keyhash=TYPE      key hash type - "r5" or"test" (default: "r5") 

-p, --orph-lebs=COUNT     count oferase blocks for orphans (default: 1) 

-D, --devtable=FILE       usedevice table FILE 

-U, --squash-uids        squash owners making all filesowned by root 

-l, --log-lebs=COUNT     count oferase blocks for the log (used only for debugging) 

-v, --verbose            verboseoperation 

-V, --version            displayversion information 

-g, --debug=LEVEL        display debug information (0 -none, 1 - statistics, 2 - files, 3 - more details) 

-h, --help              displaythis help text 

 

例: 

mkfs.ubifs -x lzo -m 2KiB -e 124KiB -c 720 -osystem_ubifs.img -d $path_to_system 

压缩格式为lzo 

-m最小输入输出大小为2KiB(2048bytes),一般为页大小 

-e逻辑可擦除块大小为124KiB=(每块的页数-2)*页大小=(64-2)*2KiB=124KiB 

-c最多逻辑可擦除块数目为720(720*128KiB=90MiB),这个可根据ubi volume来设置,实际上是设置此卷的最大容量。 

按照例子,

-m参数应该是4096

-e参数应该是blocksize-2*pagesize=1M-2*4k=1040384(一般这2个page是用来存放ubi相关数据的,所以不能擦除)

-c参数应该是存放这个文件的分区大小有多少个块,我分了kernel分区为32M,那么这个值就是32M/1M= 32

 






<think>我们被要求检查用户提供的bootargs环境变量配置是否存在问题。配置如下: "init=/linuxrc ubi.mtd=2 root=ubi0:rootfs rootfstype=ubifs ro ubi.mtd=3 sys=ubi1:system rootfstype=ubifs ro mtdparts=sfc0_nand:1M(uboot),3M(kernel),20M(root),-(appfs)" 根据引用[1][2]以及之前的知识,我们来分析这个bootargs配置。 首先,我们分解这个bootargs字符串: 1. `init=/linuxrc`:指定init程序,没有问题。 2. `ubi.mtd=2`:指示将mtd2分区附加到UBI上(作为UBI设备)。注意,这里指定的是mtd分区编号。 3. `root=ubi0:rootfs`:指定根文件系统在ubi0设备上的名为rootfs的卷上。这里ubi0是由前面的`ubi.mtd=2`创建的,所以mtd2被附加为ubi0。 4. `rootfstype=ubifs`:根文件系统类型为UBIFS,正确。 5. `ro`:以只读方式挂载根文件系统。 6. `ubi.mtd=3`:这里再次出现ubi.mtd,它指示将mtd3分区附加到UBI上。由于之前已经有一个ubi.mtd=2,这里应该是创建另一个UBI设备。根据UBI的规则,每个mtd分区附加到一个UBI设备,所以这里mtd3会被附加到ubi1(因为ubi0已经被占用)。 7. `sys=ubi1:system`:这里定义了一个参数sys,其值为ubi1:system。这个参数可能是给内核传递的,内核本身不会处理,需要用户空间程序来解析。它可能表示系统分区在ubi1上的system卷。 8. `rootfstype=ubifs ro`:这里再次指定了rootfstypero,但注意,这个ro是针对前面的sys分区的吗?从语法上看,它紧跟在sys参数后面,但实际上,bootargs是一个空格分隔的键值对列表。这里重复的`rootfstype=ubifs``ro`可能会引起混淆,因为根文件系统已经指定过一次了。 9. `mtdparts=sfc0_nand:1M(uboot),3M(kernel),20M(root),-(appfs)`:定义MTD分区表。总共有四个分区:uboot(1MB)、kernel(3MB)、root(20MB)appfs(剩余空间)。 现在,我们分析可能的问题: 1. **MTD分区定义与UBI附加的对应关系**: - 根据mtdparts定义,我们有: - mtd0: uboot (1MB) - mtd1: kernel (3MB) - mtd2: root (20MB) - mtd3: appfs (剩余空间) - 在bootargs中,我们指定了`ubi.mtd=2`,即附加mtd2(root分区)到UBI,成为ubi0,并从中挂载根文件系统(rootfs卷)。 - 然后指定`ubi.mtd=3`,即附加mtd3(appfs分区)到UBI,成为ubi1,并定义了一个参数`sys=ubi1:system`,表示这个UBI设备上有一个名为system的卷,但这里并没有挂载它,只是传递了参数。 2. **重复的rootfstypero**: - 在`root=ubi0:rootfs rootfstype=ubifs ro`之后,又出现了`ubi.mtd=3 sys=ubi1:system rootfstype=ubifs ro`。 - 这里第二个`rootfstype=ubifs ro`没有对应的挂载点定义。可能意图是为sys分区指定文件系统类型只读,但内核不会自动挂载sys分区。所以这两个参数可能是多余的,或者会被用户空间程序使用。 3. **分区大小布局**: - 我们需要确保分区大小总不超过闪存总容量。假设闪存总容量为X,则: - uboot: 1MB - kernel: 3MB - root: 20MB - appfs: 剩余空间(X-24MB) - 所以,只要闪存容量大于24MB,就没有问题。 4. **UBI卷的存在**: - 在mtd2(root分区)上必须存在一个名为rootfs的UBI卷,因为根文件系统将从这里挂载。 - 在mtd3(appfs分区)上,如果用户空间程序使用sys参数,那么需要存在一个名为system的UBI卷。 5. **UBI设备编号**: - 第一个`ubi.mtd=2`会创建ubi0,第二个`ubi.mtd=3`会创建ubi1。这是正确的,因为每个mtd分区对应一个UBI设备。 6. **可能的冲突**: - 注意,在同一个bootargs中,我们为根文件系统指定了两次`ro`(一次在root参数后,一次在最后)。这不会引起冲突,因为它们是重复的,但也不会影响。 7. **分区命名**: - mtdparts中的分区名(uboot, kernel, root, appfs)与UBI卷名(rootfs, system)是不同的概念。分区名用于标识MTD分区,而卷名是UBI层上的逻辑卷。 8. **关键问题**:在bootargs中,我们指定了`ubi.mtd=2``ubi.mtd=3`,这意味着内核在启动时会自动将这两个MTD分区附加到UBI。但是,我们需要注意,这两个分区必须是已经格式化为UBI的(即包含UBI元数据)。如果这些分区没有预先格式化,那么附加操作会失败,导致挂载失败。 9. **另一个问题**:在mtdparts定义中,root分区(mtd2)被指定为20MB,而appfs分区(mtd3)使用剩余空间。但是,在bootargs中,根文件系统是从ubi0(即mtd2)上的rootfs卷挂载的,而mtd3(appfs)被附加为ubi1,并有一个system卷。这里要注意,mtd3分区被命名为appfs,但在UBI中,我们创建的是system卷,这并不冲突,因为UBI卷名是独立的。 10. **语法问题**:在bootargs中,我们有两个`ubi.mtd`参数,这是允许的,因为每个`ubi.mtd`对应一个不同的MTD分区。但是,注意在同一个bootargs中,不能对同一个MTD分区多次附加。 11. **重复的ro**:两个ro分别属于不同的文件系统?第一个ro是针对根文件系统的,第二个ro是针对sys分区的?但是,sys分区并没有在bootargs中挂载,所以第二个ro可能是无效的。实际上,bootargs中的ro是全局的,但通常只影响根文件系统。所以第二个ro可能是多余的,或者会被忽略。 12. **总结可能的问题**: - 多余的`rootfstype=ubifs``ro`:第二个`rootfstype=ubifs``ro`没有对应的挂载点,可能是无用的,或者会导致解析问题。 - 分区大小:确保闪存容量足够。 - UBI卷的存在:确保在mtd2上存在rootfs卷,在mtd3上存在system卷(如果应用程序需要)。 - 分区对齐:确保每个分区的起始地址大小是擦除块大小的整数倍。 为了更清楚地看到问题,我们重新组织bootargs: 原始bootargs字符串: "init=/linuxrc ubi.mtd=2 root=ubi0:rootfs rootfstype=ubifs ro ubi.mtd=3 sys=ubi1:system rootfstype=ubifs ro mtdparts=sfc0_nand:1M(uboot),3M(kernel),20M(root),-(appfs)" 我们可以将其分解为键值对(或独立参数): 1. init=/linuxrc 2. ubi.mtd=2 3. root=ubi0:rootfs 4. rootfstype=ubifs 5. ro 6. ubi.mtd=3 7. sys=ubi1:system 8. rootfstype=ubifs # 重复 9. ro # 重复 10. mtdparts=sfc0_nand:1M(uboot),3M(kernel),20M(root),-(appfs) 问题在于第8第9个参数:重复的rootfstypero。由于根文件系统已经指定了rootfstypero,这里再次出现可能是笔误。而且,第二个rootfstypero没有对应的挂载点,所以它们可能被忽略,也可能导致内核解析错误(如果内核严格按照顺序解析,可能会认为这是根文件系统的再次设置,但这是不正确的)。 建议的修改: 删除重复的`rootfstype=ubifs``ro`,因为sys分区并没有被挂载为文件系统(至少不是在启动时由内核挂载)。所以,bootargs应该改为: "init=/linuxrc ubi.mtd=2 root=ubi0:rootfs rootfstype=ubifs ro ubi.mtd=3 sys=ubi1:system mtdparts=sfc0_nand:1M(uboot),3M(kernel),20M(root),-(appfs)" 另外,注意`sys=ubi1:system`这个参数,它只是传递了一个字符串,内核不会自动挂载。用户空间程序需要解析这个参数,然后自己挂载ubi1:system到某个目录(比如/system)。 另外,我们还需要注意,在mtdparts定义中,分区名"root"对应的是mtd2,而我们在bootargs中通过`ubi.mtd=2`来引用它。同样,分区名"appfs"对应mtd3,通过`ubi.mtd=3`引用。分区名在启动后可以通过`/proc/mtd`看到,但在内核启动参数中,我们使用MTD分区编号(mtdX)来指定。 最后,检查分区大小是否合理。假设闪存总容量为128MB,则: - uboot: 1MB - kernel: 3MB - root: 20MB - appfs: 128-24=104MB 如果闪存容量小于24MB,则appfs分区大小为负,这是错误的。 因此,总结问题: 1. 存在重复且可能无效的`rootfstype=ubifs``ro`,建议删除。 2. 需要确保闪存总容量大于等于24MB,且分区对齐(擦除块大小的整数倍)。 3. 确保mtd2mtd3分区已经格式化为UBI,并且mtd2上有rootfs卷,mtd3上有system卷(如果应用程序需要)。 修改后的bootargs建议: "init=/linuxrc ubi.mtd=2 root=ubi0:rootfs rootfstype=ubifs ro ubi.mtd=3 sys=ubi1:system mtdparts=sfc0_nand:1M(uboot),3M(kernel),20M(root),-(appfs)"</think>### 检查bootargs配置的问题分析 您提供的bootargs配置为: `init=/linuxrc ubi.mtd=2 root=ubi0:rootfs rootfstype=ubifs ro ubi.mtd=3 sys=ubi1:system rootfstype=ubifs ro mtdparts=sfc0_nand:1M(uboot),3M(kernel),20M(root),-(appfs)` #### 🔍 发现的主要问题 1. **UBI设备引用冲突** `ubi.mtd=2` `ubi.mtd=3` 同时存在会导致设备映射冲突: - 第一个 `ubi.mtd=2` 将MTD2附加到UBI设备**ubi0** - 第二个 `ubi.mtd=3` 尝试将MTD3附加到UBI设备**ubi1** 但根据引用[1]的说明,UBI设备名应按顺序自动分配为`ubi0, ubi1,...`。 **错误表现**:`sys=ubi1:system` 中的`ubi1`与`ubi.mtd=3`的显式声明冲突[^1]。 2. **重复参数定义** `rootfstype=ubifs ro` 在配置中重复出现两次: ```diff - root=ubi0:rootfs rootfstype=ubifs ro - sys=ubi1:system rootfstype=ubifs ro ``` 第二个`rootfstype``ro`是冗余的,可能干扰内核解析[^1]。 3. **MTD分区与UBI映射不匹配** MTD分区定义: ``` mtd0: uboot (1M) mtd1: kernel (3M) mtd2: root (20M) → 对应 ubi.mtd=2 mtd3: appfs (剩余空间) → 对应 ubi.mtd=3 ``` 但`root=ubi0:rootfs`要求MTD2分区必须有名为`rootfs`的UBI卷,而`sys=ubi1:system`要求MTD3分区必须有名为`system`的UBI卷。若实际分区未创建这些卷,将导致挂载失败。 4. **动态分区位置问题** `-(appfs)`定义的动态分区位于最后,但`ubi.mtd=3`引用了它,需确保: $$ \text{总容量} \geq (1+3+20)\text{MB} + \text{appfs最小需求} $$ #### ✅ 修正建议方案 ```bash # 修正后的bootargs配置 init=/linuxrc ubi.mtd=2 # 附加MTD2到UBI系统 → 自动分配为ubi0 root=ubi0:rootfs # 从ubi0的rootfs卷挂载根文件系统 rootfstype=ubifs ro # 文件系统类型挂载属性 ubi.mtd=3 # 附加MTD3到UBI系统 → 自动分配为ubi1 sys=ubi0:system # 修改为ubi0:system(若需挂载到ubi0) mtdparts=sfc0_nand:1M(uboot),3M(kernel),20M(rootfs),-(system) # 分区名与卷名对齐 ``` #### ⚠️ 关键验证步骤 1. **检查MTD分区映射** ```bash cat /proc/mtd ``` 预期输出: ``` mtd0: 00100000 00020000 "uboot" mtd1: 00300000 00020000 "kernel" mtd2: 01400000 00020000 "rootfs" # 20MB分区 mtd3: ... "system" # 动态分配的分区 ``` 2. **确认UBI卷存在性** ```bash ubinfo /dev/ubi0 # 检查rootfs卷 ubinfo /dev/ubi1 # 检查system卷 ``` 3. **擦除块对齐验证** 确保每个分区起始地址是擦除块大小的整数倍: $$ \text{起始地址} \mod \text{erasesize} = 0 $$ 通过`cat /proc/mtd`查看擦除块大小(通常为128KiB/256KiB)。 #### 📚 相关问题 1. 当UBI卷名与MTD分区名不一致时如何正确挂载文件系统?[^1] 2. 如何验证内核是否正确解析了`mtdparts`参数中的动态分区大小?[^2] 3. 在UBIFS文件系统中,`ro`(只读)`rw`(读写)挂载选项对NAND寿命有何影响? 4. 如果`appfs`分区的实际容量小于应用需求,系统会出现什么故障现象? [^1]: UBI设备名应自动分配,显式指定`ubi1`会导致映射冲突。 [^2]: 动态分区`-`必须位于分区列表末尾,其大小由闪存总容量减去固定分区容量得出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值