3. RK3588启动流程与文件系统加载

RK3588 的启动过程是一条严格分阶段的信任链:从芯片内部固化的 BootROM 开始,逐级加载并校验下一阶段镜像,最终把控制权交给 Linux 内核,由内核挂载 rootfs 并启动用户态 init。理解这条链路,是文件系统定制与 rootfs 优化的前提——因为 rootfs 能否被正确挂载,取决于分区表、启动参数、内核配置和存储介质四者是否一致。

一、四阶段启动链路与职责划分

RK3588 上电后依次经历 BootROM、U-Boot(含 TPL/SPL 与 proper)、Kernel、rootfs 四个阶段。每一阶段的镜像来源、运行位置和核心职责都不同:

  • BootROM:固化在芯片内部,不可修改。上电后根据启动介质优先级(通常 SPI NOR → eMMC → SD → USB OTG)读取存储介质固定偏移处的引导头,加载并校验 TPL/SPL 到片内 SRAM 运行。
  • U-Boot:分为 TPL/SPL 与 proper 两级。SPL 负责初始化 DDR、时钟和基础外设,把完整 U-Boot 搬到 DDR;proper 阶段解析分区表、读取 bootargs、加载内核与 DTB,最后跳转内核入口。
  • Kernel:解压并初始化,解析 DTB 中的设备树信息,按 bootargs 中的 root= 参数定位根文件系统所在分区或设备,完成驱动探测。
  • rootfs:内核挂载成功后执行 /sbin/init(或 systemd),进入用户态,完成服务启动与登录环境构建。
RK3588 启动链路:BootROM → U-Boot → Kernel → rootfs ① BootROM 片内固化 · 不可改 读引导头 / 校验签名 加载 TPL/SPL → SRAM ② U-Boot SPL:初始化 DDR/时钟 proper:解析分区表 加载 Image + DTB ③ Kernel 解压 / 解析 DTB 按 root= 定位根分区 驱动探测 ④ rootfs 挂载成功 执行 /sbin/init 进入用户态 存储介质分区布局(GPT / parameter) uboot 0x4000 misc 0x2000 boot 0x8000 recovery 0x10000 rootfs 0x80000 分区偏移与大小由 parameter.txt / GPT 定义,U-Boot 与 Kernel 必须一致 bootargs 关键参数解析 root= 指定根文件系统设备,如 /dev/mmcblk0p5 rootfstype= ext4 / squashfs / ubifs / overlay rootwait 等待存储设备就绪后再挂载 rw / ro 根文件系统读写属性,影响 overlay 方案 加载顺序与依赖关系 上电 BootROM DDR 就绪 SPL → U-Boot 内核启动 解析 bootargs 挂载 rootfs 执行 init

二、分区表与启动参数的对应关系

RK3588 常见方案使用 GPT 分区表,同时保留 parameter.txt 描述分区偏移与大小。U-Boot 依据分区表定位 boot 分区中的内核镜像与 DTB,内核则依据 bootargs 中的 root= 参数定位 rootfs 分区。两者必须指向同一块存储介质上的同一分区,否则会出现“内核启动成功但无法挂载根文件系统”的典型故障。

分区名 典型偏移 内容 被谁读取
uboot 0x4000 idbloader.img + u-boot.itb BootROM / SPL
misc 0x2000 启动模式标志 U-Boot
boot 0x8000 Image、DTB、resource.img U-Boot
recovery 0x10000 恢复模式 ramdisk U-Boot
rootfs 0x80000 ext4 / squashfs 根文件系统 Kernel

三、实操:查看与修改启动参数

在 U-Boot 命令行中可通过 printenv 查看 bootargs,通过 setenv 修改并 saveenv 持久化。以下命令展示了把根分区切换到 eMMC 第 5 分区并启用 rootwait 的典型操作:

# 进入 U-Boot 命令行后
printenv bootargs
# 输出示例:
# console=ttyFIQ0,1500000n8 root=/dev/mmcblk0p5 rootfstype=ext4 rw rootwait

setenv bootargs console=ttyFIQ0,1500000n8 root=/dev/mmcblk0p5 \
  rootfstype=ext4 rw rootwait
saveenv
boot

内核启动日志中,与 rootfs 挂载直接相关的关键行如下,可用于快速判断挂载是否成功:

[    0.000000] Kernel command line: console=ttyFIQ0,1500000n8 \
  root=/dev/mmcblk0p5 rootfstype=ext4 rw rootwait
[    1.842310] mmcblk0: p1(uboot) p2(misc) p3(boot) p4(recovery) p5(rootfs)
[    2.105674] EXT4-fs (mmcblk0p5): mounted filesystem with ordered data mode
[    2.106012] VFS: Mounted root (ext4 filesystem) on device 179:5.
[    2.106330] Run /sbin/init as init process
若日志停在 “Waiting for root device /dev/mmcblk0p5...”,优先检查三件事:bootargs 中的 root= 是否与分区表一致、内核是否编入了对应存储控制器驱动、rootwait 是否缺失导致设备尚未就绪就尝试挂载。

四、常见误区与复盘

  • 误区一:只改分区表不改 bootargs。重新分区后 rootfs 偏移变化,但 bootargs 仍指向旧分区,导致挂载失败。应同步更新 parameter.txt 与 bootargs。
  • 误区二:忽略 rootfstype。squashfs 只读,若 bootargs 写成 rw 且未配置 overlay,用户态写入会失败。只读根需配合 overlayfs 或 tmpfs。
  • 误区三:DTB 与内核不匹配。U-Boot 加载的 DTB 若与内核版本不一致,可能出现存储控制器未使能,rootfs 自然无法挂载。
  • 误区四:缺少 rootwait。eMMC 枚举较慢时,内核可能在设备就绪前尝试挂载,加入 rootwait 可显著提升启动稳定性。
复盘要点:rootfs 挂载问题几乎都能归入“分区表—bootargs—内核配置—存储驱动”四要素。排查时按启动日志顺序逐段确认:U-Boot 是否读到 boot 分区、内核是否识别存储设备、root= 是否指向正确分区、文件系统类型是否匹配,即可快速定位根因。