4. 分区基础与存储布局

Bootloader 要找到内核,内核要挂载根文件系统,这两件事都依赖同一张“地图”——存储布局。分区表决定“从哪里开始、到哪里结束、放什么”,而底层介质类型决定“能不能按扇区随机读写、是否需要擦除块”。理解分区表与介质差异,是避免“烧录成功却启动失败”的第一道门槛。

一、核心原理:分区表是 Bootloader 与内核的共同契约

分区表本质是一段被固化的元数据,它把一块物理存储切成若干逻辑区间,并给每个区间标注起止地址、类型与属性。Bootloader 依据它定位内核分区与设备树分区,内核依据它注册块设备节点或解析 MTD 分区,根文件系统再依据它被挂载。三者必须对同一张表达成一致,否则会出现“分区偏移错位”“根文件系统找不到”等典型故障。

常见分区表类型有三类:MBR、GPT,以及嵌入式常见的MTD 分区描述(如 cmdline 中的 mtdparts)。MBR 位于 LBA0,使用 4 个主分区表项,每项记录起始 LBA 与扇区数,最大寻址 2TiB;GPT 使用 LBA1 作为主 GPT 头,包含 128 个分区项,并用 CRC32 校验,支持 64 位 LBA 与备份表,适合大容量 eMMC/UFS。MTD 分区则不是磁盘意义上的分区表,而是把 Flash 的物理擦除块按偏移切分,由内核 mtd 子系统解析。

二、MBR 与 GPT 的结构对比

对比项MBRGPT
位置LBA0(512B)LBA1 主表 + 末尾备份表
分区数量4 主分区,可扩展逻辑分区默认 128 个
容量上限2TiB(512B 扇区)约 8ZiB
校验无CRC32 头与表校验
典型场景老式 SD、小容量 NOReMMC、UFS、大容量 SD

在 Bootloader 中,U-Boot 的 gpt write 与 part list 命令可直接操作 GPT;而 MBR 常用 fdisk 或 parted 生成。注意:GPT 会在磁盘末尾保留备份表,若镜像只烧录到主表区域而截断末尾,内核可能因备份表 CRC 失败而拒绝识别。

三、MTD 与块设备:两种截然不同的访问模型

NOR 与 NAND 属于MTD 设备,访问单位是擦除块(Erase Block),写前必须擦除,且存在坏块;eMMC、SD、UFS 属于块设备,以 512B 或 4KB 扇区随机读写,内部 FTL 负责磨损均衡与坏块管理。这一差异直接决定分区布局方式:MTD 分区通常以擦除块边界对齐,块设备分区以扇区/LBA 对齐。

# MTD 分区示例(cmdline 传递)
mtdparts=nor0:256k(boot),64k(env),1m(kernel),4m(rootfs)

# 块设备分区示例(GPT)
mmcblk0p1  boot    4MiB
mmcblk0p2  env     1MiB
mmcblk0p3  kernel  16MiB
mmcblk0p4  rootfs  剩余空间
误区:把 NAND 当块设备直接 dd 写入。NAND 必须先擦除、按页写、处理坏块与 ECC,否则数据看似写入,实际读出全为 0xFF 或校验失败。

四、eMMC/SD/NAND/NOR 布局差异与场景

eMMC 通常包含 Boot Area、RPMB、User Area 三个硬件分区,Bootloader 可放在 Boot Area 或 User Area 的偏移 0 处;SD 卡无 Boot Area,Bootloader 常写入保留扇区或 FAT 分区。NOR 支持 XIP,Bootloader 可直接在片内执行,分区常按 4KB 扇区对齐;NAND 不支持 XIP,需先拷贝到 RAM,分区按擦除块(如 128KB)对齐,并预留坏块表空间。

存储介质分区布局对比 eMMC Boot Area RPMB User Area(GPT) FTL/坏块管理 SD 卡 保留扇区/Bootloader FAT/EXT 分区(MBR 或 GPT) NOR Flash boot env kernel rootfs(XIP) NAND Flash boot env kernel rootfs(UBI) 坏块表/ECC 扇区/LBA 对齐 擦除块对齐 擦除块+坏块

五、案例:从 eMMC 启动失败的复盘

某产品使用 eMMC,Bootloader 放在 User Area 偏移 0,内核分区从 16MiB 开始。烧录后串口停在 Waiting for root device。排查发现:分区表使用 MBR,但镜像写入时把 GPT 备份表区域覆盖,内核解析分区时 CRC 失败,回退到整盘扫描,导致 root= 指向的 mmcblk0p4 不存在。修正方法:统一使用 GPT,并确保末尾备份表不被截断;或在 cmdline 中显式指定 root=/dev/mmcblk0p4 rootwait 并核对分区偏移。

实操建议:在 U-Boot 中用 part list mmc 0 与 gpt verify mmc 0 验证分区表;在 Linux 中用 cat /proc/mtd 与 lsblk -f 分别确认 MTD 与块设备分区,两者不可混用。

六、方法流程:如何选择分区方案

  1. 确认介质类型:eMMC/SD 走块设备 + GPT/MBR;NOR/NAND 走 MTD + mtdparts 或 UBI。
  2. 确认 Bootloader 存放位置:eMMC Boot Area 或 User Area 偏移 0;NOR 偏移 0;NAND 需预留坏块。
  3. 按擦除块或扇区对齐分区边界,避免跨块写入。
  4. 为 env、kernel、rootfs、data 预留独立分区,并保留备份表或坏块表空间。
  5. 在 Bootloader 与内核 cmdline 中保持分区名、偏移、大小一致。

分区布局不是“随便切一刀”,而是 Bootloader、内核与根文件系统三方共同遵守的地址契约。理解 MBR/GPT 的元数据差异、MTD 与块设备的访问模型差异,以及 eMMC/SD/NAND/NOR 的物理约束,才能在烧录、启动与升级中做到一次成功。