buildroot+qemu+arm64虚拟环境多种方式启动linux内核

Qemu:QEMU是一款开源的硬件虚拟化软件,可以在不同的主机平台上运行虚拟机。它通过动态的二进制转换,模拟CPU,并且提供一组设备模型,使它能够运行多种未修改的客户机OS。QEMU采用全系统仿真,可以模拟完整的计算机系统,包括处理器、内存、存储和外围设备。它提供硬件仿真,允许在一个虚拟环境中运行不同体系结构的操作系统和应用程序。QEMU可以与KVM一起使用,进而接近本地速度运行虚拟机。
目前,QEMU里面32bit arm平台比较多,如vexpress-a9,versatilepb等, 64bit arm64平台比较少。而Linero开发的”virt”平台可同时支持32bit 和64bit的arm(详见QEMU源码/hw/arm/virt.c )。“virt”支持 PCI,virtio,最新的arm CPU 和 大容量RAM。如果只想在最新的arm cpu上面运行linux虚拟机,不在意特定的硬件,”virt”平台是最佳选择

环境选择

Qemu环境搭建 QEMU emulator version 7.2.8 版本不能太低 否则会报错。

Buildroot版本:buildroot2023.11

Linux kernel版本:5.10.208

Uboot版本: uboot 2018

busybox版本:busybox-1.36-1

首先需要对buildroot进行配置,从而完成uboot,kernel,rootfs的构建。

选择qemu virt平台进行arm64 cortex a57的测试。

编译

以buildroot方式编译三大件的配置方式

buildroot配置:buildroot中提供了qemu-virt环境的默认配置。路径在/buildroot/configs/qemu_aarch64_virt_defconfig中为其默认配置,这里做了一些修改,将其覆盖即可:

BR2_aarch64=y
BR2_cortex_a57=y
BR2_TOOLCHAIN_EXTERNAL=y
BR2_TOOLCHAIN_EXTERNAL_LINARO_AARCH64=y
BR2_TOOLCHAIN_EXTERNAL_GDB_SERVER_COPY=y
BR2_SYSTEM_DHCP="eth0"
BR2_ROOTFS_POST_IMAGE_SCRIPT="board/qemu/post-image.sh"
BR2_ROOTFS_POST_SCRIPT_ARGS="$(BR2_DEFCONFIG)"
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="5.10.208"
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/qemu/aarch64-virt/linux.config"
BR2_LINUX_KERNEL_INSTALL_TARGET=y
BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y
BR2_TARGET_ROOTFS_CPIO=y
BR2_TARGET_ROOTFS_CPIO_GZIP=y
BR2_TARGET_ROOTFS_CPIO_UIMAGE=y
BR2_TARGET_ROOTFS_EXT2=y
BR2_TARGET_ROOTFS_EXT2_4=y
BR2_TARGET_ROOTFS_EXT2_SIZE="200M"
# BR2_TARGET_ROOTFS_TAR is not set
BR2_TARGET_UBOOT=y
BR2_TARGET_UBOOT_BUILD_SYSTEM_KCONFIG=y
BR2_TARGET_UBOOT_CUSTOM_VERSION=y
BR2_TARGET_UBOOT_CUSTOM_VERSION_VALUE="2018.11"
BR2_TARGET_UBOOT_BOARD_DEFCONFIG="qemu_arm64"

其中对uboot和linux的配置文件均为arm64架构下的qemu virt平台下的配置文件。

配置文件中指定了uboot和kernel的配置文件分别问qemu_arm64.defconfig和"board/qemu/aarch64-virt/linux.config"

进入buildroot目录:

cd buildroot
sudo make qemu_aarch64_virt_defconfig 
sudo make 

等待编译完成。

编译完成后在buildroot/output/image下会出现镜像文件。第一次编译需要下载很多依赖,需要耐心等待,如果有等待很久下载不下的情况,可以自行下载至buildroot的dl文件夹目录下。重新make的时候buildroot会自动识别安装包并解压。

自行编译三大件的方式

uboot:

sudo make ARCH=arm64 CROSS_COMPILE=~/buildroot-2023.11/output/host/opt/ext-toolchain/bin/aarch64-linux-gnu- qemu_arm64_defconfig
sudo make CROSS_COMPILE=~/buildroot-2023.11/output/host/opt/ext-toolchain/bin/aarch64-linux-gnu- -j4

需要根目录下的u-boot文件

kernel:

sudo make ARCH=arm64 CROSS_COMPILE=~/buildroot-2023.11/output/host/opt/ext-toolchain/bin/aarch64-buildroot-linux-gnu- linux.config
sudo make ARCH=arm64 CROSS_COMPILE=~/buildroot-2023.11/output/host/opt/ext-toolchain/bin/aarch64-buildroot-linux-gnu- -j8

需要Image文件,在/arch/arm64/boot目录下
linux.config内容如下:

CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_LOGGING=y
CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_SCSI_VIRTIO=y
CONFIG_ATA=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
CONFIG_MACVLAN=y
CONFIG_VIRTIO_NET=y
CONFIG_NLMON=y
CONFIG_INPUT_EVDEV=y
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_VIRTIO=y
CONFIG_TCG_TPM=y
CONFIG_TCG_TIS=y
CONFIG_DRM=y
CONFIG_DRM_VIRTIO_GPU=y
CONFIG_FB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_PL031=y
CONFIG_VIRTIO_PCI=y
CONFIG_VIRTIO_INPUT=y
CONFIG_VIRTIO_MMIO=y
CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y
CONFIG_MAILBOX=y
CONFIG_PL320_MBOX=y
CONFIG_ARM_SMMU_V3=y
CONFIG_EXT4_FS=y
CONFIG_FUSE_FS=y

busybox:

sudo make ARCH=arm64 CROSS_COMPILE=~/buildroot-2023.11/output/host/opt/ext-toolchain/bin/aarch64-buildroot-linux-gnu- defconfig
sudo make ARCH=arm64 CROSS_COMPILE=~/buildroot-2023.11/output/host/opt/ext-toolchain/bin/aarch64-buildroot-linux-gnu- -j8
sudo make install ARCH=arm64 CROSS_COMPILE=~/buildroot-2023.11/output/host/opt/ext-toolchain/bin/aarch64-linux-gnu-

在_install目录下:

cd busybox-1_36_0
mkdir -p ~/rootfs 
cp _install/* ~/rootfs/ -rf
cd ~/rootfs/

# 创建init文件
rm linuxrc
ln -s bin/busybox init

# 创建控制台设备文件
mkdir dev
mkdir proc
mkdir sys
mkdir config
mkdir debug
sudo mknod -m 600 dev/console c 5 1
sudo mknod dev/tty1 c 4 1
sudo mknod dev/tty2 c 4 2
sudo mknod dev/tty3 c 4 3
sudo mknod dev/tty4 c 4 4

# 创建配置文件目录及文件
mkdir etc
touch etc/inittab

#修改 etc/inittab 的内容如下
::sysinit:/etc/init.d/rcS
::askfirst:-/bin/sh
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a

#创建初始化脚本
mkdir -p etc/init.d/
touch etc/init.d/rcS
chmod +x etc/init.d/rcS

#初始化脚本 rcS 的内容为,注意sysfs,debugfs和configfs的mount
#!/bin/sh
export PATH=/sbin:/bin:/usr/bin:/usr/sbin;
echo "minisystem start..."
mount -t sysfs sysfs /sys
mount -t proc procfs /proc
mount -t debugfs debugfsfs /debug
mount -t configfs configfs /config
mount -o rw,remount /

#制作raw格式的最小根文件系统镜像,生成rootfs.img
find . | cpio -o -H newc | gzip > ../rootfs.img
cd ..
mkimage -A arm64 -T ramdisk -d rootfs.img rootfs.cpio.uboot

uboot启动时需要rootfs.cpio.uboot ,qemu启动只需要rootfs.img

参考链接:https://zhuanlan.zhihu.com/p/626683569

启动

启动方式一:无uboot引导,内核和根文件系统同时引导至内存中启动。(initramfs)

此种方式需要再make menconfig中将BR2_TARGET_ROOTFS_INITRAMFS选中。

在buildroot下,已整理好启动的shell命令start_qemu_aarch64_raw.sh

sudo qemu-system-aarch64 -M virt \
 -cpu cortex-a57 -nographic -smp 4 -m 512 \
 -kernel output/images/Image \
 -append "console=ttyAMA0 kmemleak=on loglevel=8" \

此种方式将根文件系统cpio文件集成至内核中,一起在内存中启动,根文件系统挂载在内存设备上,重启会导致丢失。

此时是initramfs启动方式,使用initramfs,命令行参数将不需要"root="命令。

如果没有选中BR2_TARGET_ROOTFS_INITRAMFS,可以手动以initramfs的方式运行,使用“initrd”指定cpio我文件,内核会自动识别该类型文件并在ram中进行启动。

sudo qemu-system-aarch64 -machine virt -cpu cortex-a57 -machine type=virt -m 1024 -smp 4 \
 -kernel output/images/Image \
 -append "console=ttyAMA0 kmemleak=on loglevel=8 " \
 -initrd output/images/rootfs.cpio.gz \
 -nographic \

参考链接:

https://jgsun.github.io/2018/12/17/qemu-virt-arm64/

https://zhuanlan.zhihu.com/p/426026299

https://blog.csdn.net/xunknown/article/details/124521135

启动方式二:无uboot引导,内核引导至内核启动,根文件系统挂载在本地虚拟存储设备/dev/vda上。

该引导方式需要取消buildroot配置时的Filesystem images —> cpio the root filesystem选项和Filesystem images —>initial RAM filesystem linked into linux kernel选项。此时不会将cpio文件集成至内核文件中。

如果执行过方式一,则需要:

sudo make linux-dirclean
sudo make 

若没有编译过则:

sudo make

此时编译出来之后会出现/output/images/下会出现rootfs.ext4文件。

但是最保险的方式时先全局make clean再sudo make,但是比较耗时。

使用以下指令可引导启动:

sudo qemu-system-aarch64 -machine virt -cpu cortex-a57 -machine type=virt -m 1024 -smp 4 \
 -kernel output/images/Image \
 -append "noinitrd root=/dev/vda rw console=ttyAMA0 loglevel=8" \
 -nographic -drive if=none,file=output/images/rootfs.ext4,id=hd0 \
 -device virtio-blk-device,drive=hd0 \
 --fsdev local,id=kmod_dev,path=$PWD/kmodules,security_model=none

参考链接:

https://zhuanlan.zhihu.com/p/626683569

https://blog.csdn.net/xunknown/article/details/124521135

如果没有使用buildroot进行ext4文件系统镜像的生成,也可以选择自己手动生成文件系统的镜像:

执行:

sudo dd if=/dev/zero of=rootfs_ext4.img bs=1M count=1024
sudo mkfs.ext4 rootfs_ext4.img
sudo mkdir -p tmpfs
sudo mount  -t ext4 rootfs_ext4.img  tmpfs/ -o loop
sudo cp -af ../target/* tmpfs/
sudo umount  tmpfs
chmod 777 rootfs_ext4.img

使用rootfs_ext4.img为rootfs的文件源,启动指令如下:

sudo qemu-system-aarch64 -machine virt -cpu cortex-a57 -machine type=virt -m 1024 -smp 4 \
 -kernel output/images/Image \
 -append "noinitrd root=/dev/vda rw console=ttyAMA0 loglevel=8" \
 -nographic -drive if=none,file=output/images/rootfs_ext4.img,id=hd0 \
 -device virtio-blk-device,drive=hd0 \
 --fsdev local,id=kmod_dev,path=$PWD/kmodules,security_model=none

实现重启后根文件系统中内容保存。

启动方式三:uboot引导,内核、设备树以网络方式进行引导。

在编译得到uboot.bin后,需要制作flash.bin才能够烧录至虚拟flash:

sudo dd if=/dev/zero of=flash.bin bs=4096 count=16384
sudo dd if=u-boot.bin of=flash.bin conv=notrunc bs=4096

随后运行buildroot下的uboot_start.sh脚本:

sudo qemu-system-aarch64 -machine virt \
 -cpu cortex-a57 \
 -m 1G \
 -drive file=output/images/flash.bin,format=raw,if=pflash \
 -nographic \
 -netdev type=tap,id=net0,script=board/qemu/scripts/qemu-ifup_virbr0 \
 -device e1000,netdev=net0

qemu-ifup_virbr0是qemu相关的网络配置,自己生成:

#!/bin/sh
run_cmd()
{
 echo $1
 eval $1
}
run_cmd "sudo ifconfig $1 0.0.0.0 promisc up"
run_cmd "sudo brctl addif virbr0 $1"
run_cmd "brctl show"

#point run在进入uboot后,需要完成tftp引导,由于网络已经DHCP配置好,能够ping通宿主机就可以进行传输。

tftpboot ${kernel_addr_r} zhouwenqi/Image&&tftpboot ${ramdisk_addr_r} zhouwenqi/rootfs.cpio.uboot &&tftpboot ${fdt_addr} zhouwenqi/qemu_arm64.dtb&&setenv bootargs "root=/dev/ram0 rw  init=/linuxrc earlycon console=ttyAMA0,115200"&&booti ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr}

zhouwenqi/Image是内核镜像

zhouwenqi/rootfs.cpio.uboot是根文件系统的uimage(buildroot可以自动生成,选中menuconfig中BR2_TARGET_ROOTFS_CPIO_UIMAGE即可,也可以使用mkimage指令制作)

但是这种方式会卡在内核启动start kernel处,猜测是设备树文件不匹配造成。 或者是boot命令和image内核镜像不对应造成。

制作设备树:

-M virt,dumpdtb=coretex-a57.dtb //qemu启动指令中添加此行
dtc -I dtb -O dts coretex-a57.dtb -o coretex-a57.dts //反编译为dts
cp qemu_arm64.dts ./output/build/linux-5.10.208/arch/arm64/boot/dts/arm/ //复制到内核目录下
vim Makefile //末行添加qemu_arm64.dtb
make ARCH=arm64 CROSS_COMPILE=~/buildroot-2023.11/output/host/opt/ext-toolchain/bin/aarch64-linux-gnu- dtbs //使用内核进行编译

但是还是发现起不来,卡了将近一周,最后发现是qemu的uboot启动方式的问题,在flash中通过uboot.bin镜像进行启动会导致卡在kernel_init()->kernel_init_freeable()->do_one_initcall()->of_platform_default_populate_init()->of_platform_populate()->of_platform_bus_create()->amba_device_add()->amba_device_try_add()函数中,原因未知。
故使用如下启动方式:

sudo qemu-system-aarch64 -machine virt -cpu cortex-a57 -machine type=virt -m 1024 -smp 4 \
 -kernel u-boot \
 -nographic -netdev type=tap,id=net0,script=board/qemu/scripts/qemu-ifup_virbr0  -device e1000,netdev=net0

后续的操作和上面的#point run一样。

启动方式四:uboot引导,内核、设备树从虚拟SD卡进行引导。

首先根据https://zhuanlan.zhihu.com/p/626683569中的方式制作了uboot.disk 的SD卡镜像,用于存放内核设备树和根文件系统。

根据网上的大部分资料qemu末尾添加 -sd boot.disk -nographic \即可,但是在实际运行中发现并-sd指令无法识别

sudo qemu-system-aarch64 -machine virt \
 -cpu cortex-a57 \
 -m 1G \
 -drive file=flash.bin,format=raw,if=pflash \
 -nographic \
 -sd boot.disk -nographic \

根据kvm - qemu to emulate SD-Bus and card - Stack Overflow中引导,采用后种方式

sudo qemu-system-aarch64 -machine virt \
 -cpu cortex-a57 \
 -m 1G \
 -drive file=flash.bin,format=raw,if=pflash \
 -nographic \
 -device sdhci-pci -device sd-card,drive=mydrive -drive id=mydrive,if=none,format=raw,file=boot.disk

虽然能够启动,sd卡却没有办法识别,后来发现是因为qemu virt没有SD卡设备,这种方式不再讨论。

Zynq是Xilinx公司开发的一种可编程的SoC(System-on-Chip)芯片,与Arm Cortex-A9内核和FPGA(Field-Programmable Gate Array)逻辑单元相结合,可通过软件和硬件定义实现更高的性能和更灵活的功能。Buildroot是一个开源的工具,可用于构建嵌入式系统,它使用Makefiles和patch文件来自定义软件包的构建过程,并生成根文件系统和可引导映像。WiFi是一种无线网络技术,可以通过无线信号进行数据传输和接收。 在使用Zynq内核时,可以使用Buildroot来构建嵌入式系统,并在其中包括WiFi模块。此过程需要选择适合的配置和软件包,以便实现所需的功能。为此,可以使用Buildroot提供的菜单配置工具,或手动编辑配置文件进行定制。随后,将生成的根文件系统和可引导映像烧写到目标设备上,以使其可以运行所需的软件和可用的WiFi连接。 在设置WiFi连接时,需要配置网络设置并选择适当的无线接入点。这可以通过命令行或图形用户界面完成,例如使用WPA Supplicant工具或网络管理器应用程序。在Zynq中使用WiFi时,应考虑板载天线、功耗和稳定性等因素,并选择适当的WiFi模块和天线组合。此外,还应考虑网络安全问题,例如使用加密协议和身份验证来保护数据传输。 综上所述,使用Zynq内核Buildroot嵌入式系统可以包括WiFi连接,但在实现此过程时需要进行适当的配置和注意事项,以确保系统的性能和稳定性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值