目录
-
-
-
- [qemu 基础说明](#qemu 基础说明)
- [qemu 安装 和 arm64 交叉编译器安装](#qemu 安装 和 arm64 交叉编译器安装)
- [linux 内核下载和编译](#linux 内核下载和编译)
- [busybox 下载编译](#busybox 下载编译)
- [打包 initramfs](#打包 initramfs)
- [启动 qemu](#启动 qemu)
-
-
qemu 基础说明
QEMU 是一个开源的虚拟机仿真器,可模拟多种硬件架构(如 ARM、x86 等),适用于嵌入式开发、内核调试和系统测试
如果在 ubunut/deepin 系统上安装 qemu ,并启动 linux arm64 内核 initramfs 的最小系统,需要的步骤如下:
- 下载安装
qemu和arm64交叉编译器 - 下载
linux kernel内核(6.6)并编译 - 下载
busybox并编译 - 打包为
ramdisk最小系统并启动内核
另外也提供了一个 编译生成 userspace binary 的方法,可以用于测试自己对 linux 内核的开发
qemu 安装 和 arm64 交叉编译器安装
步骤如下:
shell
# 安装 qemu
sudo apt update
sudo apt install qemu-system-arm
# 打印出版本号
qemu-system-arm --version
# 安装 aarch64-linux-gnu-
sudo apt install gcc-aarch64-linux-gnu
# 打印出版本号
aarch64-linux-gnu-gcc -v
linux 内核下载和编译
shell
# 选择自己需要的内核版本
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.tar.xz
linux 内核编译,参考下面的脚本:
shell
KERNEL_VERSION="6.6"
BUILD_DIR="$(pwd)/build"
KERNEL_DIR="$BUILD_DIR/linux"
KERNEL_BUILD_DIR="$BUILD_DIR/linux/out"
CROSS_COMPILE=aarch64-linux-gnu-
ARCH=arm64
#========================
#编译内核
#========================
build_kernel() {
echo "build kernel ($KERNEL_VERSION)..."
cd "$KERNEL_DIR"
mkdir -p $KERNEL_BUILD_DIR
make ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE O=$KERNEL_BUILD_DIR dmabuf_defconfig
make -j$(nproc) ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE O=$KERNEL_BUILD_DIR Image
cd -
}
#========================
#kernel menuconfig
#========================
build_kernel_menuconfig() {
echo "make kernel ($KERNEL_VERSION) menuconfig and save..."
cd "$KERNEL_DIR"
mkdir -p $KERNEL_BUILD_DIR
make ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE O=$KERNEL_BUILD_DIR menuconfig
make -j$(nproc) ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE O=$KERNEL_BUILD_DIR savedefconfig
cp -v $KERNEL_DIR/out/defconfig $KERNEL_DIR/arch/arm64/configs/dmabuf_defconfig
cd -
}
#========================
#编译dtb all dtb
#========================
build_kernel_dtb() {
echo "build kernel ($KERNEL_VERSION)..."
cd "$KERNEL_DIR"
mkdir -p $KERNEL_BUILD_DIR
make ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE O=$KERNEL_BUILD_DIR dtbs
cd -
}
注意点:
linux内核编译的O(OUTPUT)参数表示内核编译的输出目录,这样可以保持代码目录干净menuconfig可以用于选择配置,由分布在内核里的Kconfig决定,但是需要配合savedefconfigsavedefconfig生成的配置保存在defconfig,在这里拷贝保存成了自己的配置
生的 dtb 文件,用下面命令进行反编译:
shell
dtc -I dtb -O dts -o output.dts.txt qemu-default.dtb
busybox 下载编译
使用下面命令下载 busybox:
c
wget -nc https://busybox.net/downloads/busybox-1.36.1.tar.bz2
编译方法
shell
#========================
#编译 BusyBox
#========================
build_busybox() {
echo "build BusyBox ($BUSYBOX_VERSION)..."
mkdir -p $BUSYBOX_BUILD_DIR
cd "$BUSYBOX_DIR"
make ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE KBUILD_OUTPUT=$BUSYBOX_BUILD_DIR defconfig
# 启用静态链接
sed -i 's/# CONFIG_STATIC is not set/CONFIG_STATIC=y/' $BUSYBOX_BUILD_DIR/.config
make -j$(nproc) ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE KBUILD_OUTPUT=$BUSYBOX_BUILD_DIR
cd -
}
注意:
- 这里强制启用了静态链接,因为没有拷贝对应的 glibc lib 到根文件系统
打包 initramfs
shell
#========================
#构建根文件系统
#========================
build_rootfs() {
echo "generate rootfs..."
rm -rf "$ROOTFS_DIR"
mkdir -p "$ROOTFS_DIR"
# 安装 busybox 到 rootfs
cd "$BUSYBOX_DIR"
make ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE KBUILD_OUTPUT=$BUSYBOX_BUILD_DIR CONFIG_PREFIX="$ROOTFS_DIR" install
cd -
# 创建必要目录
mkdir -p "$ROOTFS_DIR"/{proc,sys,dev,etc/init.d}
#直接将 busybox 拷贝为 init
cp -v "$ROOTFS_DIR"/bin/busybox "$ROOTFS_DIR"/init
# 拷贝启动文件
cp -v "$BUILD_DIR"/rootfs_files/rcS "$ROOTFS_DIR"/etc/init.d/rcS
chmod +x "$ROOTFS_DIR"/etc/init.d/rcS
}
#========================
#打包 initramfs
#========================
pack_initramfs() {
echo "pack initramfs..."
cd "$ROOTFS_DIR"
find . | cpio -o --format=newc | gzip -9 > "$INITRD_FILE"
cd -
echo "okay initramfs : $INITRD_FILE"
}
其中启动文件 rcS 内容:
shell
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
/sbin/mdev -s
echo "Welcome to wangchen ARM64 QEMU System!"
exec /sbin/getty -L -n -l /bin/sh ttyAMA0 115200 vt100
启动 qemu
真实的 HW 启动必须要指定 dtb 文件,但是这里使用的 virt machine 的 qemu 启动,所以:
可以不指定 dtb, 使用默认 virt 的 dtb 启动 qemu:
shell
run_qemu() {
echo "starting qemu arm64..."
qemu-system-aarch64 \
-machine virt \
-cpu cortex-a72 \
-smp 2 \
-m 512 \
-kernel "$KERNEL_BUILD_DIR/arch/arm64/boot/Image" \
-initrd "$INITRD_FILE" \
-append "console=ttyAMA0,115200 earlyprintk=serial loglevel=8" \
-nographic \
-serial mon:stdio
}
说明:
-machine virt:使用通用 ARM64 虚拟机平台
-smp 2 :设置处理器为双核
-m 512 :设置内存大小为 512M
-nographic:禁用图形界面,使用串口输出(适合服务器环境)
virt 的 dtb 可以使用下面的命令 dump 出来:
shell
# 注意 virt 后加逗号,之后不能有空格
qemu-system-aarch64 \
-machine virt,dumpdtb=qemu_default.dtb \
-cpu cortex-a72 \
-smp 2 \
-m 512
QEMU 的 virt 机器模型会自动生成一个 dtb,这个自动生成的 dtb 包括:
- 内存节点(根据 -m 参数,比如
-m 1G → reg = <0 0x40000000 0 0x40000000>); - 中断控制器(
GIC); - 串口(pl011 或 8250);
- 定时器、
RTCetc
这些节点的内容也可以从 /proc/device-tree 显示出来