u-boot

这里我们使用 docker 编译我们的 u-bootkernel 编译 u-boot

wget <https://source.denx.de/u-boot/u-boot/-/archive/v2025.04/u-boot-v2025.04.tar.gz>
tar xf u-boot-v2025.04.tar.gz
cd u-boot-v2025.04
make qemu_arm64_defconfig
... # just build it
cp u-boot.bin ../images # 复制到统一目录

kernel

wget <https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.14.6.tar.xz>
tar xf linux-6.14.6.tar.xz
cd linux-6.14.6
make ARCH=arm64 defconfig # kernel 会根据 ARCH 寻找 configs
make LLVM=1 ARCH=arm64 -j$(nproc) # 支持 LLVM 就不用 GCC 了
cp arch/arm64/boot/Image ../images

initramfs 制作

我们使用 alpine 作为 rootfs

首先制作一个 init 脚本用于初始化基本 rootfs , 这个脚本仅仅进入 shell 给我们测试, 后面会更新跳转实际 rootfsinit 脚本. 注意使用 chmod +x init 为脚本添加执行权限.

#!/bin/sh

echo "Loading, please wait..."

[ -d /dev ] || mkdir -m 0755 /dev
[ -d /root ] || mkdir --mode=0700 /root
[ -d /sys ] || mkdir /sys
[ -d /proc ] || mkdir /proc
[ -d /tmp ] || mkdir /tmp
[ -d /mnt ] || mkdir /mnt

# Mount /proc and /sys:
mount -n proc /proc -t proc
mount -n sysfs /sys -t sysfs

# Note that this only becomes /dev on the real filesystem if udev's scripts
# are used; which they will be, but it's worth pointing out
#mount -t tmpfs -o mode=0755 udev /dev
[ -e /dev/console ] || mknod /dev/console c 5 1
[ -e /dev/null ] || mknod /dev/null c 1 3

# this will scan device update /dev list
mdev -s

/bin/sh -i
mkdir rootfs
wget <https://dl-cdn.alpinelinux.org/alpine/v3.21/releases/aarch64/alpine-minirootfs-3.21.3-aarch64.tar.gz>
tar xf alpine-minirootfs-3.21.3-aarch64.tar.gz -C rootfs
cd rootfs
cp ../init . # copy init script to rootfs
find . | cpio -o -H newc | gzip > ../images/rootfs.cpio.gz

dump dtb

我们将qemu模拟设备的机器设备树dump出来, 这里我们的模拟机器是 virt, 相关的其他 arm 机器查询https://www.qemu.org/docs/master/system/target-arm.html

qemu-system-aarch64 -machine virt,dumpdtb=virt.dtb -cpu cortex-a72 -smp 4 -m 2G -nographic