手动给OrangePi Zero3编译U-Boot制作根文件系统BusyBox
Orange Pi Zero 3 使用全志H618芯片,基于ARM Cortex-A53架构。
整体流程概览
编译工具链 → 编译ATF → 编译U-Boot → 编译Linux内核 → 制作根文件系统(BusyBox) → 烧写SD卡
第一步:准备编译环境
在Ubuntu 22.04 x86_64主机上操作:
sudo apt update
sudo apt install -y \
git make gcc bison flex bc \
libssl-dev libncurses-dev \
python3 python3-dev python3-setuptools \
swig device-tree-compiler \
gcc-aarch64-linux-gnu \
binutils-aarch64-linux-gnu \
u-boot-tools \
parted dosfstools \
wget unzip
设置交叉编译工具链环境变量:
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
第二步:编译 ARM Trusted Firmware (ATF/BL31)
H618需要ATF作为BL31,U-Boot依赖它:
git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git
cd trusted-firmware-a
make PLAT=sun50i_h616 DEBUG=0 bl31
# 编译产物:build/sun50i_h616/release/bl31.bin
export BL31=$(pwd)/build/sun50i_h616/release/bl31.bin
cd ..
第三步:编译 U-Boot
git clone https://github.com/u-boot/u-boot.git
cd u-boot
# 使用 Orange Pi Zero 3 的默认配置
make orangepi_zero3_defconfig
# (可选)图形化配置
# make menuconfig
# 编译(指定BL31路径)
make -j$(nproc) BL31=$BL31
# 编译产物:u-boot-sunxi-with-spl.bin
ls -lh u-boot-sunxi-with-spl.bin
cd ..
第四步:编译 Linux 内核
git clone --depth=1 https://github.com/torvalds/linux.git
# 或者用orangepi官方内核(更推荐,驱动更完整):
# git clone --depth=1 https://github.com/orangepi-xunlong/linux-orangepi.git -b orange-pi-6.1-sun50iw9
cd linux # 或 linux-orangepi
# 使用通用ARM64配置
make defconfig
# 或者用官方内核时用:
# make sun50iw9p1smp_defconfig
# 图形化裁剪内核(可选)
make menuconfig
# 编译内核镜像 + 设备树 + 模块
make -j$(nproc) Image dtbs modules
# 关键产物:
# arch/arm64/boot/Image — 内核镜像
# arch/arm64/boot/dts/allwinner/sun50i-h618-orangepi-zero3.dtb — 设备树
第五步:制作根文件系统(BusyBox)
wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2
tar xf busybox-1.36.1.tar.bz2
cd busybox-1.36.1
make defconfig
# 必须配置为静态链接(嵌入式系统推荐)
# Settings → Build static binary (no shared libs) → 选中
make menuconfig
make -j$(nproc)
make install # 安装到 ./_install 目录
cd ..
构建完整根文件系统:
mkdir -p rootfs
cp -r busybox-1.36.1/_install/* rootfs/
# 创建必要目录
mkdir -p rootfs/{dev,proc,sys,tmp,etc/init.d,lib,lib64,usr/lib}
# 创建设备节点
sudo mknod rootfs/dev/console c 5 1
sudo mknod rootfs/dev/null c 1 3
sudo mknod rootfs/dev/tty c 5 0
# 创建 etc/fstab
cat > rootfs/etc/fstab << 'EOF'
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
devtmpfs /dev devtmpfs defaults 0 0
EOF
# 创建启动脚本
cat > rootfs/etc/init.d/rcS << 'EOF'
#!/bin/sh
mount -a
mount -t devtmpfs devtmpfs /dev
echo "Welcome to OrangePi Zero3 Linux!"
hostname orangepi
EOF
chmod +x rootfs/etc/init.d/rcS
# 创建 inittab
cat > rootfs/etc/inittab << 'EOF'
::sysinit:/etc/init.d/rcS
::respawn:-/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/sbin/swapoff -a
::shutdown:/bin/umount -a -r
EOF
# 安装内核模块到rootfs
cd linux # 或 linux-orangepi
make modules_install INSTALL_MOD_PATH=../rootfs
cd ..
第六步:制作 SD 卡镜像并烧写
6.1 分区布局
SD卡布局:
┌─────────────────────────────────────────┐
│ 0~7KB : MBR / 保留 │
│ 8KB~1MB : U-Boot (u-boot-sunxi-with-spl.bin)│
│ 1MB~257MB: FAT32 分区 /boot (内核+dtb) │
│ 257MB~末 : ext4 分区 / (根文件系统) │
└─────────────────────────────────────────┘
6.2 创建镜像文件(推荐先用文件模拟,避免操作失误)
# 创建2GB空镜像
dd if=/dev/zero of=sdcard.img bs=1M count=2048
# 分区(FAT32 boot + ext4 rootfs)
parted sdcard.img --script \
mklabel msdos \
mkpart primary fat32 1MiB 257MiB \
mkpart primary ext4 257MiB 100%
# 挂载为 loop 设备
sudo losetup -fP sdcard.img
LOOPDEV=$(sudo losetup -j sdcard.img | cut -d: -f1)
echo "Loop device: $LOOPDEV"
# 格式化
sudo mkfs.vfat -F32 -n BOOT ${LOOPDEV}p1
sudo mkfs.ext4 -L rootfs ${LOOPDEV}p2
6.3 烧写 U-Boot
# U-Boot烧写到8KB偏移(SPL需要在扇区16)
sudo dd if=u-boot/u-boot-sunxi-with-spl.bin \
of=$LOOPDEV \
bs=1024 seek=8 conv=notrunc
6.4 写入内核和设备树到 boot 分区
sudo mkdir -p /mnt/boot /mnt/rootfs
sudo mount ${LOOPDEV}p1 /mnt/boot
sudo mount ${LOOPDEV}p2 /mnt/rootfs
# 复制内核和dtb
sudo cp linux/arch/arm64/boot/Image /mnt/boot/
sudo cp linux/arch/arm64/boot/dts/allwinner/sun50i-h618-orangepi-zero3.dtb /mnt/boot/
# 创建U-Boot启动脚本
cat > boot.cmd << 'EOF'
setenv bootargs "console=ttyS0,115200 root=/dev/mmcblk0p2 rootwait rw"
load mmc 0:1 ${kernel_addr_r} Image
load mmc 0:1 ${fdt_addr_r} sun50i-h618-orangepi-zero3.dtb
booti ${kernel_addr_r} - ${fdt_addr_r}
EOF
# 编译为U-Boot可识别的脚本镜像
mkimage -C none -A arm64 -T script -d boot.cmd boot.scr
sudo cp boot.scr /mnt/boot/
6.5 写入根文件系统
sudo cp -a rootfs/* /mnt/rootfs/
# 卸载
sudo umount /mnt/boot
sudo umount /mnt/rootfs
sudo losetup -d $LOOPDEV
6.6 烧写到真实SD卡
# 确认你的SD卡设备名!!(极其重要,写错会损坏系统)
lsblk # 插入SD卡前后对比,确认设备名,如 /dev/sdb 或 /dev/mmcblk0
# 烧写镜像
sudo dd if=sdcard.img of=/dev/sdX bs=4M status=progress conv=fsync
# 将 /dev/sdX 替换为你的实际SD卡设备
sync
第七步:启动和调试
7.1 串口连接
Orange Pi Zero 3 的调试串口(UART0):
– TX → GPIO Pin 8
– RX → GPIO Pin 10
– GND → GPIO Pin 6
– 波特率:115200
# 主机上用 minicom 或 picocom 连接
sudo minicom -D /dev/ttyUSB0 -b 115200
# 或
sudo picocom -b 115200 /dev/ttyUSB0
7.2 预期启动日志
U-Boot SPL ...
U-Boot ...
=> (U-Boot命令行,或自动执行boot.scr)
Starting kernel ...
[ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd034]
...
Welcome to OrangePi Zero3 Linux!
/ #
常见问题排查
| 现象 | 原因 | 解决 |
|---|---|---|
| 无任何串口输出 | U-Boot未正确烧写/偏移错误 | 确认 seek=8(KB单位) |
| SPL启动后停止 | BL31路径错误 | 重新编译U-Boot并指定BL31= |
| 内核panic找不到rootfs | root= 参数错误 | 改为root=/dev/mmcblk0p2 |
| 设备树找不到 | dtb文件名错误 | ls /mnt/boot/ 确认文件名 |
| BusyBox报错缺少库 | 未静态编译 | menuconfig中启用static binary |
小贴士
- 🔁 建议先用官方镜像确认硬件正常,再做手动编译
- 🔧 如遇内核驱动不完整,推荐使用 OrangePi官方内核(
linux-orangepi仓库) - 📦 根文件系统可以后续替换为 Alpine Linux 的 minirootfs 获得更完整的包管理器
- 💾 整个流程建议在 Ubuntu 22.04 虚拟机或WSL2中操作
如有任何步骤遇到问题,欢迎告诉我具体报错信息!