Qemu模拟arm64启动Uboot + Linux

📅 2026/6/18 16:54:30
Qemu模拟arm64启动Uboot + Linux
目的由 U-Boot 引导 Linux 是一套非常经典的“全栈”仿真玩法虽然Qemu可以跳过U-Boot直接启动Linux但是要还原真实硬件的启动流程U-Boot是绕不开要调试和学习的以此简单记录下。使用Qemu可以用于早期的方案验证提前排除风险。无实物纯模拟不用担心硬件bug省去了很多调试力气。一、uboot1.1 安装依赖库编译uboot时需要编译主机工具而编译工具又依赖于一些常用的开发库。sudo apt install -y uuid-dev libssl-dev libgnutls28-dev libncurses-dev swig python3-dev u-boot-tools mtd-utils pkg-config cpio1.2 编译uboot下载编译启动不再赘述。ubifs依赖于ubiubi依赖于mtdmtd可以是norspinand。#下载 wget https://ftp.denx.de/pub/u-boot/u-boot-2026.01.tar.bz2 tar -jxvf u-boot-2026.01.tar.bz2 cd u-boot-2026.01 #配置已开启ubi配置 make ARCHarm CROSS_COMPILEaarch64-linux-gnu- qemu_arm64_defconfig make ARCHarm CROSS_COMPILEaarch64-linux-gnu- menuconfig 或以下方法 cat EOF .config CONFIG_CMD_MTDy CONFIG_MTDy CONFIG_FLASH_CFI_DRIVERy CONFIG_SYS_FLASH_CFIy CONFIG_MTD_NOR_FLASHy CONFIG_MTD_DEVICEy CONFIG_CMD_UBIy CONFIG_CMD_UBIFSy EOF make ARCHarm CROSS_COMPILEaarch64-linux-gnu- olddefconfig #编译 make ARCHarm CROSS_COMPILEaarch64-linux-gnu- -j4 cp u-boot.bin ../ 启动 qemu-system-aarch64 -machine virt -cpu cortex-a53 -smp 2 -m 512 -kernel u-boot -nographic1.3 启动uboot启动uboot可以识别两个mtd设备以及操作ubi卷。镜像文件可以裸放到支持norflash上ubi卷上或者ubifs文件系统中。需要uboot支持读接口获取镜像文件并启动因为重心不在此就不继续考究了。Bloblist at 0 not found (err-2) alloc space exhausted ptr 400 limit 0 Bloblist at 0 not found (err-2) U-Boot 2026.01 (Jun 11 2026 - 11:35:10 0800) DRAM: 512 MiB using memory 0x5e637000-0x5f677000 for malloc() Core: 51 devices, 14 uclasses, devicetree: board Flash: 64 MiB Loading Environment from Flash... *** Warning - bad CRC, using default environment In: serial,usbkbd Out: serial,vidconsole Err: serial,vidconsole No USB controllers found Net: eth0: virtio-net#32 Hit any key to stop autoboot: 0 mtd list List of MTD devices: * nor0 - device: flash0 - parent: root_driver - driver: cfi_flash - path: /flash0 - type: NOR flash - block size: 0x20000 bytes - min I/O: 0x1 bytes - 0x000000000000-0x000002000000 : nor0 * nor1 - device: flash0 - parent: root_driver - driver: cfi_flash - path: /flash0 - type: NOR flash - block size: 0x20000 bytes - min I/O: 0x1 bytes - 0x000000000000-0x000002000000 : nor11.4 初探UBI擦除norattach mtd设备创建ubi卷。uboot下似乎只支持读没有支持ubifs格式化、写入的操作因此无法挂载ubifs文件系统。我想这是安全的行为如果在uboot下创建文件系统要做好和kernel的版本同步。这个很麻烦也很容易把不一致性传递给kernel导致长期使用后ubifs的累加错误。 protect off all Un-Protect Flash Bank # 1 Un-Protect Flash Bank # 2 erase all Erase Flash Bank # 1 ................................................................................................................................................................................................................................................................ done Erase Flash Bank # 2 ................................................................................................................................................................................................................................................................ done ubi part nor0 0 force ubi0: attaching mtd0 ubi0: scanning is finished ubi0: empty MTD device detected ubi0: attached mtd0 (name nor0, size 32 MiB) ubi0: PEB size: 131072 bytes (128 KiB), LEB size: 130944 bytes ubi0: min./max. I/O unit sizes: 1/1, sub-page size 1 ubi0: VID header offset: 64 (aligned 64), data offset: 128 ubi0: good PEBs: 256, bad PEBs: 0, corrupted PEBs: 0 ubi0: user volume: 0, internal volumes: 1, max. volumes count: 128 ubi0: max/mean erase counter: 0/0, WL threshold: 4096, image sequence number: 0 ubi0: available PEBs: 252, total reserved PEBs: 4, PEBs reserved for bad PEB handling: 0 ubi create system 0xa00000 dynamic Creating dynamic volume system of size 10485760 ubi info layout Volume information dump: vol_id 0 reserved_pebs 81 alignment 1 data_pad 0 vol_type 3 name_len 6 usable_leb_size 130944 used_ebs 81 used_bytes 10606464 last_eb_bytes 130944 corrupted 0 upd_marker 0 skip_check 0 name system Volume information dump: vol_id 2147479551 reserved_pebs 2 alignment 1 data_pad 0 vol_type 3 name_len 13 usable_leb_size 130944 used_ebs 2 used_bytes 261888 last_eb_bytes 2 corrupted 0 upd_marker 0 skip_check 0 name layout volume ubi ubi ubifsload ubifsls ubifsmount ubifsumount ubifsmount system UBIFS error (pid: 1): cannot open system, error -22 Error reading superblock on volume system errno-22!二、kernel2.1 编译kernel编译启动不再赘述。#配置去掉nor后续模拟nand make ARCHarm64 defconfig ./scripts/config --enable DEBUG_INFO \ --enable DEBUG_KERNEL \ --enable GDB_SCRIPTS \ --enable KALLSYMS_ALL \ --enable FRAME_POINTER ./scripts/config --disable MTD_CFI \ --disable MTD_GENPROBE \ --disable MTD_CFI_AMDSTD \ --disable MTD_CFI_UTIL \ --disable MTD_PHYSMAP \ --disable MTD_PHYSMAP_OF cat EOF .config # MTD 核心与分区支持 CONFIG_MTDy CONFIG_MTD_PARTITIONSy CONFIG_MTD_CMDLINE_PARTSy CONFIG_MTD_CHARy # 核心 1启用 block2mtd 驱动 CONFIG_MTD_BLOCKy CONFIG_MTD_BLOCK2MTDy # 核心 2启用 nandsim 驱动及其依赖的 NAND 框架 CONFIG_MTD_RAW_NANDy CONFIG_MTD_NAND_NANDSIMm # UBI 与 UBIFS 配置 CONFIG_MTD_UBIy CONFIG_MTD_UBI_WL_THRESHOLD4096 CONFIG_MTD_UBI_BEB_LIMIT20 CONFIG_UBIFS_FSy CONFIG_UBIFS_FS_ADVANCED_COMPRy CONFIG_UBIFS_FS_LZOy CONFIG_UBIFS_FS_ZLIBy EOF make ARCHarm64 olddefconfig #编译 make ARCHarm64 CROSS_COMPILEaarch64-linux-gnu- -j8 cp arch/arm64/boot/Image ../ #启动 qemu-system-aarch64 \ -machine virt,virtualizationon \ -cpu cortex-a53 \ -kernel arch/arm64/boot/Image \ -append consolettyAMA0 nokaslr \ -nographic2.2 制作rootfs解决Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)问题需要busybox做个rootfs。#下载 wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2 tar -jxvf busybox-1.36.1.tar.bz2 cd busybox-1.36.1/ #配置启用静态链接 ,配置为静态编译。简单无需拷贝动态链接库 make ARCHarm64 CROSS_COMPILEaarch64-linux-gnu- defconfig sed -i s/^# CONFIG_STATIC.*/CONFIG_STATICy/ .config #关闭tc解决编译问题 sed -i s/CONFIG_TCy/CONFIG_TCn/ .config #编译 make ARCHarm64 CROSS_COMPILEaarch64-linux-gnu- -j4 make ARCHarm64 CROSS_COMPILEaarch64-linux-gnu- install #打包rootfs mkdir -p rootfs cp -av busybox-1.36.1/_install/* rootfs/ cd rootfs mkdir -p {dev,etc,lib,proc,sys,mnt,root,etc/init.d,tmp} #创建基础设备节点 sudo mknod -m 666 dev/tty1 c 4 1 sudo mknod -m 666 dev/tty2 c 4 2 sudo mknod -m 666 dev/tty3 c 4 3 sudo mknod -m 666 dev/tty4 c 4 4 sudo mknod -m 666 dev/console c 5 1 sudo mknod -m 666 dev/null c 1 3 #创建初始启动脚本 cat etc/init.d/rcS EOF #!/bin/sh mount -t proc proc /proc mount -t sysfs sysfs /sys mount -t devtmpfs devtmpfs /dev mount -t tmpfs tmpfs /tmp EOF chmod x etc/init.d/rcS #制作initramfs镜像 find . -print0 | cpio --null -ov --formatnewc | gzip -9 ../initrd.img cd .. #容量信息 :~/linux$ ls -alh ./ -rw-r--r-- 1 l16952 l16952 33M Jun 16 10:24 Image -rw-r--r-- 1 l16952 l16952 1.2M Jun 16 10:45 initrd.img -rw-r--r-- 1 l16952 l16952 1.6M Jun 16 09:37 u-boot.bin三、uboot启动kernel3.1 制作镜像创建虚拟磁盘存放Imageinitrd.img。让uboot通过virtio读取并加载启动#创建128MB的空磁盘文件 dd if/dev/zero ofdisk.img bs1M count128 #烧录内核 Image 到磁盘的 0 偏移处 dd ifImage ofdisk.img bs1M convnotrunc #烧录根文件系统 initrd.img 到磁盘偏移 50MB 处 dd ifinitrd.img ofdisk.img bs1M seek50 convnotrunc3.2 启动镜像#定义一块virtio块设备运行程序访问该设备获取disk.img中的镜像 qemu-system-aarch64 \ -machine virt,virtualizationon \ -cpu cortex-a53 \ -m 1024M \ -bios u-boot.bin \ -drive filedisk.img,formatraw,ifnone,idmydisk \ -device virtio-blk-device,drivemydisk \ -nographic #进uboot命令行执行以下操作 #读取内核Image virtio read 0x40080000 0x0 0x11170 #读取initrd.img virtio read 0x44000000 0x19000 0xBB8 #设置启动参数 setenv bootargs rdinit/sbin/init consolettyAMA0 loglevel8 #指定 initrd 内存段的起始地址和具体十六进制大小 booti 0x40080000 0x44000000:0x125cb4 $fdtcontroladdr3.3 自动启动使用环境变量或者脚本但是因为没有固化到介质中所以重启qemu仍会丢失#设置环境变量 setenv bootcmd virtio read 0x40080000 0x0 0x11170; virtio read 0x44000000 0x19000 0xBB8; setenv bootargs rdinit/sbin/init consolettyAMA0 loglevel8; booti 0x40080000 0x44000000:0x125cb4 $fdtcontroladdr #保存环境变量 saveenv #kernel下reboot Please press Enter to activate this console. ~ #reboot umount: devtmpfs busy - remounted read-only umount: cant unmount /: Invalid argument swapoff: cant open /etc/fstab: No such file or directory The system is going down NOW! Sent SIGTERM to all processes Sent SIGKILL to all processes Requesting system reboot #boot下reset Hit any key to stop autoboot: 0 reset resetting ...3.4 固化启动配置让uboot拥有两块flash使用文件来模拟存储boot镜像和环境变量。#生成第一块 64MB 的 Flash并把 u-boot.bin 重新烧进去 dd if/dev/zero ofpflash.img bs1M count64 dd ifu-boot.bin ofpflash.img convnotrunc #生成第二块 64MB 的 Flash专门给 U-Boot 存环境变量 dd if/dev/zero ofpflash_env.img bs1M count64 #用双flash命令启动QEMU qemu-system-aarch64 \ -machine virt,virtualizationon \ -cpu cortex-a53 \ -m 1024M \ -drive filepflash.img,formatraw,ifpflash \ -drive filepflash_env.img,formatraw,ifpflash \ -drive filedisk.img,formatraw,ifnone,idmydisk \ -device virtio-blk-device,drivemydisk \ -nographic #保存环境变量这次是真实写入pflash_env.img中 setenv bootcmd virtio read 0x40080000 0x0 0x11170; virtio read 0x44000000 0x19000 0xBB8; setenv bootargs rdinit/sbin/init consolettyAMA0 loglevel8; booti 0x40080000 0x44000000:0x125cb4 $fdtcontroladdr saveenv #后续直接用QEMU命令即可启动ubootkernel qemu-system-aarch64 \ -machine virt,virtualizationon \ -cpu cortex-a53 \ -m 1024M \ -drive filepflash.img,formatraw,ifpflash \ -drive filepflash_env.img,formatraw,ifpflash \ -drive filedisk.img,formatraw,ifnone,idmydisk \ -device virtio-blk-device,drivemydisk \ -nographic