搭建linux调试环境 (二)-- 基于u-boot搭建qemu的vexpress环境
目录:
搭建linux调试环境 (一)-- qemu环境搭建vexpress开发平台
搭建linux调试环境 (二)-- 基于u-boot搭建qemu的vexpress环境
搭建linux调试环境 (三)-- vexpress添加系统调用
上一篇文章搭建了基于zImage的qemu环境,基本的环境配置已经可以使用,为了还原真正的嵌入式ARM启动场景,搭建基于u-boot的qemu环境。
1. u-boot下载及编译
1.1 下载地址 https://ftp.denx.de/pub/u-boot/,本文使用的版本为2019.10
1.2 下载后解压进行配置
# vim Makefile
CROSS_COMPILE = arm-linux-gnueabi-
# vim config.mk
ARCH = arm
编译
sly@ubuntu:~/develop/u-boot-2019.10$ make vexpress_ca9x4_defconfig
sly@ubuntu:~/develop/u-boot-2019.10$ make -j20
1.3 qemu启动u-boot
sly@ubuntu:~/develop$ qemu-system-arm -M vexpress-a9 -m 512M -nographic -kernel u-boot-2019.10/u-boot
----省略部分打印,下面打印环境变量
=> print
arch=arm
baudrate=38400
board=vexpress
board_name=vexpress
bootargs=root=/dev/sda1 rw console=ttyAMA0,38400n8 mem=1024M mtdparts=armflash:1M@0x800000(uboot),7M@0x1000000(kernel),24M@0x2000000(initrd) mmci.fmax=190000 devtmpfs.mount=0 vmalloc=256M
console=ttyAMA0,38400n8
cpu=armv7
kernel_addr=0x44100000
kernel_addr_r=0x80008000
loadaddr=0x80008000
maxramdisk=0x1800000
mmc_boot=if mmc dev ${devnum}; then devtype=mmc; run scan_dev_for_boot_part; fi
mtd=armflash:1M@0x800000(uboot),7M@0x1000000(kernel),24M@0x2000000(initrd)
pxefile_addr_r=0x88000000
ramdisk_addr=0x44800000
ramdisk_addr_r=0x61000000
root=/dev/sda1 rw
scan_dev_for_boot=echo Scanning ${devtype} ${devnum}:${distro_bootpart}...; for prefix in ${boot_prefixes}; do run scan_dev_for_extlinux; run scan_dev_for_scripts; done;
scan_dev_for_boot_part=part list ${devtype} ${devnum} -bootable devplist; env exists devplist || setenv devplist 1; for distro_bootpart in ${devplist}; do if fstype ${devtype} ${devnum}:${distro_bootpart} bootfstype; then run scan_dev_for_boot; fi; done; setenv devplist
scan_dev_for_extlinux=if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}${boot_syslinux_conf}; then echo Found ${prefix}${boot_syslinux_conf}; run boot_extlinux; echo SCRIPT FAILED: continuing...; fi
scan_dev_for_scripts=for script in ${boot_scripts}; do if test -e ${devtype} ${devnum}:${distro_bootpart} ${prefix}${script}; then echo Found U-Boot script ${prefix}${script}; run boot_a_script; echo SCRIPT FAILED: continuing...; fi; done
scriptaddr=0x88000000
stderr=serial
stdin=serial
stdout=serial
ubifs_boot=env exists bootubipart || env set bootubipart UBI; env exists bootubivol || env set bootubivol boot; if ubi part ${bootubipart} && ubifsmount ubi${devnum}:${bootubivol}; then devtype=ubi; run scan_dev_for_boot; fi
vendor=armltd
2. 准备uImage的内核,指定加载地址,编译uImage
sly@ubuntu:~/develop/linux-5.3.7$ make LOADADDR=0x60003000 uImage -j4 HOSTCC scripts/dtc/dtc.o HOSTCC scripts/dtc/flattree.o HOSTCC scripts/dtc/fstree.o HOSTCC scripts/dtc/data.o。。。。省略部分。。。 LD vmlinux.o MODPOST vmlinux.o MODINFO modules.builtin.modinfo KSYM .tmp_kallsyms1.o KSYM .tmp_kallsyms2.o LD vmlinux SORTEX vmlinux SYSMAP System.map OBJCOPY arch/arm/boot/Image Kernel: arch/arm/boot/Image is ready GZIP arch/arm/boot/compressed/piggy_data AS arch/arm/boot/compressed/piggy.o LD arch/arm/boot/compressed/vmlinux OBJCOPY arch/arm/boot/zImage Kernel: arch/arm/boot/zImage is ready UIMAGE arch/arm/boot/uImage Image Name: Linux-5.3.7 Created: Mon Dec 30 21:39:49 2019 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 4583688 Bytes = 4476.26 KiB = 4.37 MiB Load Address: 60003000 Entry Point: 60003000 Kernel: arch/arm/boot/uImage is ready
3.配置qemu的网络
Qemu虚拟机在u-boot启动时,需要将uImage加载到内存,而uImage从哪里来?可以通过TFTP服务器下载uImage到内存指定地址。而在这之前需要通过桥接方式将网络链接到Ubuntu系统
3.1 配置Qemu与主机的网络连接
采用桥接网络连接Host主机通信
主机内核需要支持tun/tap模块
VMware为机器再添加一张网卡,用于配置桥接网络
3.2 配置Xubuntu主机
安装桥接网络依赖的两个工具:
sudo apt install uml-utilities bridge-utils
创建tun设备文件:/dev/net/tun(一般会自动创建)
修改/etc/network/interfaces文件配置网络
sly@ubuntu:~/develop/u-boot-2019.10$ vi /etc/network/interfaces
# interfaces(5) file used by ifup(8) and ifdown(8)
auto lo
iface lo inet loopback
#查看自己的网口的名称
auto ens33
iface ens33 inet static
address 192.168.199.150
netmask 255.255.255.0
gateway 192.168.199.2
#这是VMware添加的第二张网卡,用来给br0绑定
#这张网卡的连接方式是桥接或者NAT或者主机模式都可以,只要下面设置br0时设置正确就可以,参照br0的说明
#auto ens38
#br0设置成静态ip方便自己调试,ip地址可以看下ens38自动获取时的网段,需要设置在同一网段,否则会无法使用
auto br0
iface br0 inet static
address 192.168.189.152
netmask 255.255.255.0
#iface br0 inet dhcp
bridge_ports ens38
# The tap0 network interface(s)
#供qemu的u-boot使用的server地址,这这里绑定到了br0上,所以需要设置为和br0同一网段的ip
auto tap0
iface tap0 inet manual
iface tap0 inet static
address 192.168.189.20
netmask 255.255.255.0
pre-up tunctl -t tap0 -u root # 创建一个tap0接口,只允许root用户访问
pre-up ifconfig tap0 0.0.0.0 promisc up # 打开tap0接口
post-up brctl addif br0 tap0 # 在虚拟网桥中增加一个tap0接口
重启机器
sly@ubuntu:~$ sudo reboot
查看网络状况
sly@ubuntu:~/develop$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:0c:29:f6:0e:ad brd ff:ff:ff:ff:ff:ff
inet 192.168.199.150/24 brd 192.168.199.255 scope global ens33
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fef6:ead/64 scope link
valid_lft forever preferred_lft forever
3: ens38: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
link/ether 00:0c:29:f6:0e:b7 brd ff:ff:ff:ff:ff:ff
4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 00:0c:29:f6:0e:b7 brd ff:ff:ff:ff:ff:ff
inet 192.168.189.152/24 brd 192.168.189.255 scope global br0
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fef6:eb7/64 scope link
valid_lft forever preferred_lft forever
5: tap0: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
link/ether aa:2c:ce:3d:1d:3f brd ff:ff:ff:ff:ff:ff
inet 192.168.189.20/24 brd 192.168.189.255 scope global tap0
valid_lft forever preferred_lft forever
inet6 fe80::a82c:ceff:fe3d:1d3f/64 scope link
valid_lft forever preferred_lft forever
2.2 主机安装TFTP以便于u-boot从主机获取uImage
a 安装
apt-get install tftp-hpa tftpd-hpa xinetd
b 修改配置文件,设置TFTP服务器目录,并且创建对应的目录,将uImage和dtb文件拷贝进去:
# /etc/default/tftpd-hpa TFTP_USERNAME="tftp" TFTP_DIRECTORY="/home/sly/develop/tftpboot" TFTP_ADDRESS=":69" TFTP_OPTIONS="--secure"
c 重启tftp服务
sudo /etc/init.d/tftpd-hpa restart
d 设置u-boot中的内核启动参数 vi include/configs/vexpress_common.h
#define CONFIG_BOOTCOMMAND \ "tftp 0x60003000 uImage;tftp 0x60500000 vexpress-v2p-ca9.dtb; \ setenv bootargs 'root=/dev/mmcblk0 console=ttyAMA0'; \ bootm 0x60003000 - 0x60500000;" #define CONFIG_IPADDR 192.168.189.100 #define CONFIG_SERVERIP 192.168.189.20 #define CONFIG_NETMASK 255.255.255.0
删除同文件中如下代码
#define CONFIG_EXTRA_ENV_SETTINGS \ CONFIG_PLATFORM_ENV_SETTINGS \ BOOTENV \ "console=ttyAMA0,38400n8\0" \ "dram=1024M\0" \ "root=/dev/sda1 rw\0" \ "mtd=armflash:1M@0x800000(uboot),7M@0x1000000(kernel)," \ "24M@0x2000000(initrd)\0" \ "flashargs=setenv bootargs root=${root} console=${console} " \ "mem=${dram} mtdparts=${mtd} mmci.fmax=190000 " \ "devtmpfs.mount=0 vmalloc=256M\0" \ "bootflash=run flashargs; " \ "cp ${ramdisk_addr} ${ramdisk_addr_r} ${maxramdisk}; " \ "bootm ${kernel_addr} ${ramdisk_addr_r}\0"
e 重新编译u-boot后,启动qemu
sly@ubuntu:~/develop/u-boot-2019.10$ make
f 启动qemu添加网络参数,因为我们自己在/etc/network/interfaces已经预先设置了网络环境,所以qemu的ifup和ifdown显示指定为不使用,并且挂上之前制作的文件系统
sudo qemu-system-arm -M vexpress-a9 -m 512M -nographic -kernel u-boot-2019.10/u-boot -net nic -net tap,ifname=tap0,script=no,downscript=no -sd rootfs.ext3
这里有个小问题。第一次启动u-boot的时候下载uImage总是失败,手动在u-boot里下载一下后再重新执行上面的命令,向后就可以成功下载了
3.启动和停止过程写道脚本中方便使用,后续功能逐步添加
sly@ubuntu:~/develop$ vi start.sh #!/bin/sh sudo mount -t ext3 rootfs.ext3 tmp -o loop sudo cp -rf rootfs/* tmp/ sudo umount tmp echo "start kernel with $1" #传入参数k,直接以zImage方式启动,否则使用u-boot导入uImage启动 if [ $1 = "k" ]; then qemu-system-arm -M vexpress-a9 -m 512m -kernel /home/sly/develop/linux-5.3.7/arch/arm/boot/zImage -dtb linux-5.3.7/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic -append "root=/dev/mm cblk0 console=ttyAMA0" -sd rootfs.ext3 -s else #拷贝文件到tftp目录 #cp -rf cp -rf linux-5.3.7/arch/arm/boot/uImage tftpboot/ #cp -rf linux-5.3.7/arch/arm/boot/bootp/vexpress-v2p-ca9.dtb tftpboot/ sudo qemu-system-arm -M vexpress-a9 -m 512M -nographic -kernel u-boot-2019.10/u-boot -net nic -net tap,ifname=tap0,script=no,downscript=no -sd rootfs.ext3 fi
sly@ubuntu:~/develop$ vi stop.sh #!/bin/sh ps -aux | grep qemu-system-arm | grep -v grep | awk '{print $2}' | xargs kill -9