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
  • 相关阅读:
    素数个数(素数➕dfs)
    最小正子段和
    set<int> 的用法
    C
    map的用法
    B
    威佐夫博弈
    Stars(树状数组)
    upper_bound和lower_bound的用法
    超级大水题(还是自己过不了的水题)
  • 原文地址:https://www.cnblogs.com/edver/p/12117349.html
Copyright © 2011-2022 走看看