zoukankan      html  css  js  c++  java
  • Ubuntu下基于u-boot搭建qemu的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" 
            "dram=1024M" 
            "root=/dev/sda1 rw" 
            "mtd=armflash:1M@0x800000(uboot),7M@0x1000000(kernel)," 
                "24M@0x2000000(initrd)" 
            "flashargs=setenv bootargs root=${root} console=${console} " 
                "mem=${dram} mtdparts=${mtd} mmci.fmax=190000 " 
                "devtmpfs.mount=0  vmalloc=256M" 
            "bootflash=run flashargs; " 
                "cp ${ramdisk_addr} ${ramdisk_addr_r} ${maxramdisk}; " 
                "bootm ${kernel_addr} ${ramdisk_addr_r}"

      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
  • 相关阅读:
    Java实现 洛谷 P1060 开心的金明
    (Java实现) 洛谷 P1605 迷宫
    (Java实现) 洛谷 P1605 迷宫
    (Java实现)洛谷 P1093 奖学金
    (Java实现)洛谷 P1093 奖学金
    Java实现 洛谷 P1064 金明的预算方案
    Java实现 洛谷 P1064 金明的预算方案
    (Java实现) 洛谷 P1031 均分纸牌
    QT树莓派交叉编译环开发环境搭建(附多个exe工具下载链接)
    武则天红人对唐睿宗的桃色报复(如此缺少城府,注定了要在宫廷中过早地出局)
  • 原文地址:https://www.cnblogs.com/edver/p/12117349.html
Copyright © 2011-2022 走看看