构建 Avaota A1 的根文件系统
串口打印出 Starting kernel ... 之后,即使内核把所有驱动都初始化完毕,屏幕上也不会凭空出现 shell。Linux 还要找到根分区,从中执行第一个用户进程 /sbin/init,再由 init 启动串口登录和板级服务。
rootfs 提供 Linux 启动后所需的用户空间文件。这一篇使用 Buildroot 生成能够完成硬件检查的 AArch64 根文件系统,并通过 overlay 添加板级启动脚本。
选择基础系统工具
在 configs/avaota_a1_mainline_defconfig 中加入:
BR2_PACKAGE_ALSA_UTILS=y
BR2_PACKAGE_ALSA_UTILS_AMIXER=y
BR2_PACKAGE_ALSA_UTILS_APLAY=y
BR2_PACKAGE_ALSA_UTILS_SPEAKER_TEST=y
BR2_PACKAGE_MTD=y
BR2_PACKAGE_EVTEST=y
BR2_PACKAGE_USBUTILS=y
BR2_PACKAGE_LIBDRM=y
BR2_PACKAGE_LIBDRM_INSTALL_TESTS=y
BR2_PACKAGE_DROPBEAR=y
BR2_PACKAGE_ETHTOOL=y
BR2_PACKAGE_IPERF3=y
这些工具分别观察音频、MTD、输入、USB、DRM、SSH 和网络链路。工具存在不等于相应驱动已经工作;它们只是把内核状态转换为可检查输出。
Buildroot 会把目标程序及其依赖库交叉编译后放入 output/target。不要在该目录中直接运行 AArch64 程序,也不要把 output/host 与目标工具混淆:
| 目录 | 运行平台 | 用途 |
|---|---|---|
output/host | 开发主机 | genimage、交叉工具链和主机构建辅助程序 |
output/staging | 开发主机使用的目标 sysroot | 目标头文件与库,供交叉编译链接 |
output/target | AArch64 板端 | rootfs 生成前的目录树 |
output/images | 部署产物 | ext4、内核、DTB 和整盘镜像 |
这一区分决定了排错位置:软件包编译失败检查 host/staging,板端命令缺失检查 target,烧录后缺失则继续检查 images 是否吸收了 target。
添加板级 overlay 文件
创建 board/avaota/a1-mainline/rootfs-overlay/etc/init.d/S99avaota-validate:
#!/bin/sh
case "$1" in
start)
log=/var/log/avaota-validation.log
{
echo "Avaota A1 peripheral inventory"
uname -a
echo "[block]"
lsblk
echo "[network]"
ip addr show
echo "[usb]"
lsusb 2>/dev/null || true
echo "[graphics]"
ls -l /dev/dri 2>/dev/null || true
echo "[audio]"
aplay -l 2>/dev/null || true
} > "$log" 2>&1
;;
esac
设置可执行权限:
chmod +x board/avaota/a1-mainline/rootfs-overlay/etc/init.d/S99avaota-validate
脚本把一次启动的基础设备清单保存到 /var/log/avaota-validation.log。命令失败使用 || true,避免某个未支持外设阻止系统完成启动。
overlay 在生成文件系统前覆盖到 output/target,适合保存板级静态文件和 init 脚本。它不会自动把主机源码目录映射到运行系统;每次修改 overlay 后都要重新生成 rootfs。脚本名以 S99 开头,表示在 SysV init 的常规服务之后运行,因此它记录的是用户空间已经基本建立后的设备状态,不用于诊断内核挂载根分区之前的故障。
|| true 只用于非关键盘点项。/sbin/init、串口登录和根文件系统检查不能用这种方式忽略,否则系统会把核心失败伪装成一次“完成”的启动。
检查 init、内核模块和 ext4 镜像
make avaota_a1_mainline_defconfig
make -j"$(nproc)"
Buildroot 输出中需要同时存在:
output/images/rootfs.ext2
output/target/sbin/init
output/target/lib/modules/7.2.0-avaota-a1-mainline/
检查文件系统本体,而不是只看 output/target:
e2fsck -fn output/images/rootfs.ext2
tune2fs -l output/images/rootfs.ext2 \
| grep 'Filesystem volume name'
debugfs -R 'stat /sbin/init' output/images/rootfs.ext2
debugfs -R 'ls -l /lib/modules' output/images/rootfs.ext2
只读检查应通过,卷标应为 rootfs,并能在镜像内部找到 init 和唯一的内核模块目录。output/target 正确但 rootfs.ext2 缺文件,说明修改后没有重新生成文件系统镜像。
模块目录必须与 make -s -C output/build/linux-custom kernelrelease 完全相同。Linux 加载模块时比较 vermagic;目录名相同但模块来自另一份内核配置,仍可能拒绝加载。因此发布时需要同时哈希 Image、DTB 和 rootfs,而不能只记录 rootfs 文件名。
系统通过 root=LABEL=rootfs 定位根设备,因此 tune2fs 读出的卷标必须是 rootfs。eMMC 的 /dev/mmcblkN 编号可能随控制器枚举顺序改变,使用卷标可以避免把启动配置绑定到某个设备编号。