• QEMU模拟ATF启动


    QEMU模拟ATF启动

    通过qemu模拟ATF的启动,即启动流程为:

    bl1
    bl2
    bl31
    bl33
    kernel

    其中bl33为uboot

    Qemu

    1. apt方式下载

      # 不推荐以apt-get方式安装,版本较低
      # 后续启动kernel可能失败
      sudo apt-get install qemu
      # 查看ARM64平台版本
      qemu-system-aarch64 --version
      
      • 1
      • 2
      • 3
      • 4
      • 5
    2. 源码安装

      去官网下载最新的版本,这里下载qemu-7.1.0,并解压

      # 下载
      wget https://download.qemu.org/qemu-7.1.0.tar.xz
      # 解压
      xz -d qemu-7.1.0.tar.xz
      tar xvf qemu-7.1.0.tar
      
      • 1
      • 2
      • 3
      • 4
      • 5
    3. 相关库安装

      sudo apt-get install libcap-dev
      sudo apt-get install pkg-config
      sudo apt-get install zlib1g-dev libglib2.0-dev
      sudo apt-get install libpixman-1-dev
      sudo apt install python3-pip
      pip3 install --user meson
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      # ninja
      sudo apt-get install re2c
      git clone https://github.com/ninja-build/ninja.git
      cd ninja && ./configure.py --bootstrap  
      sudo cp ./ninja /usr/bin/
      ninja --version
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    4. 问题解决

      • virtio-9p (virtfs) on Linux requires libcap-ng-devel and libattr-devel

        wget https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/libcap-ng/0.7.7-3.1/libcap-ng_0.7.7.orig.tar.gz
        cd libcap-ng-0.7.7
        ./autogen.sh
        ./configure
        make
        sudo make install
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
    5. 编译安装

      ./configure --target-list=x86_64-softmmu,x86_64-linux-user,arm-softmmu,arm-linux-user,aarch64-softmmu,aarch64-linux-user --enable-kvm
      make -j16
      sudo make install
      # 查看版本
      qemu-system-aarch64 --version
      
      • 1
      • 2
      • 3
      • 4
      • 5

    U-boot

    1. 下载uboot

      git clone https://source.denx.de/u-boot/u-boot.git
      
      • 1
    2. 编译uboot

      export ARCH=arm64
      export CROSS_COMPILE=aarch64-linux-gnu- 
      make qemu_arm64_defconfig
      make -j16
      
      • 1
      • 2
      • 3
      • 4
    3. uboot位置

      ./u-boot.bin
      
      • 1

    Kernel

    1. 下载kernel

      进入官网,下载稳定版本的,这里下载linux-5.19.6.tar.xz,并解压

      # 下载
      https://www.kernel.org/
      # 解压
      xz -d linux-5.19.6.tar.xz
      tar xvf linux-5.19.6.tar
      
      • 1
      • 2
      • 3
      • 4
      • 5
    2. 编译kernel

      export ARCH=arm64
      export CROSS_COMPILE=aarch64-linux-gnu-
      make defconfig
      make -j16
      
      • 1
      • 2
      • 3
      • 4
    3. Image位置

      ./arch/arm64/boot/Image
      
      • 1

    Rootfs

    1. 下载buildroot

      进入官网,下载稳定版本,这里下载buildroot-2022.05.2.tar.xz,并解压

      # 下载
      https://buildroot.org/download.html
      # 解压
      xz -d xz -d buildroot-2022.05.2.tar.xz
      tar xvf buildroot-2022.05.2.tar
      
      • 1
      • 2
      • 3
      • 4
      • 5
    2. 配置

      make ARCH=arm64 menuconfig
      
      • 1

      如出现Unable to find the ncurses libraries or the required header files,需要安装以下库

      sudo apt-get install libncurses5-dev libncursesw5-dev
      
      • 1
      • Target Options

        Target Architecture:AArch64(little endian)

        Target Architecture Variant:cortex-A53

        其他默认不变。

      • Toolchain

        这里让buildroot自己去下载适配的工具链

      • System configuration

        这里默认不变

      • Filesystem images

        ext2/3/4 root filesystem:y

        • ex2/3/4 variant:ext4
    3. 编译

      注意不能-j进行多核编译

      sudo make
      
      • 1

    ATF

    1. 下载ATF

      git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git
      
      • 1
    2. 编译

      export ARCH=arm64
      export CROSS_COMPILE=aarch64-linux-gnu-
      make PLAT=qemu all DEBUG=1
      
      • 1
      • 2
      • 3

      TIPS:默认调试版本日志等级为40(INFO),发布版本中为20(NOTICE),可加LOG_LEVEL=50参数开启VERBOSE日志。

    3. bin文件位置

      build/qemu/debug
      
      • 1

      生成bl1.bin,bl2.bin,bl31.bin等文件

    启动

    新建qemu_test文件夹,并进入。

    1. qemu启动u-boot

      qemu-system-aarch64 \
           -M  virt \
           -cpu cortex-a53 \
           -smp 2 \
           -m 2048M \
           -kernel ../u-boot-master/u-boot \
           -nographic
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7

      TIPS:

      解决qemu启动输出参数较多,添加启动选项保存到配置文件中,如下

      -writeconfig qemu-test.conf
      
      • 1

      下次启动时,直接加载该配置文件即可

      qemu-system-aarch64 –readconfig qemu-test.conf
      
      • 1

      退出qemu,按住Ctrl+A,松开后再输入X即可。

    2. qemu启动kernel

      qemu-system-aarch64 \
           -M virt \
           -cpu cortex-a53 \
           -smp 2 \
           -m 2048M \
           -kernel ../linux-5.19.6/arch/arm64/boot/Image \
           -append "console=ttyAMA0 root=/dev/vda" \
           -nographic
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

      这里由于缺少根文件系统rootfs,会打印end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)

    3. qemu启动rootfs(kernel)

      qemu-system-aarch64 \
           -M virt \
           -cpu cortex-a53 \
           -smp 2 \
           -m 2048M \
           -kernel ../linux-5.19.6/arch/arm64/boot/Image \
           -drive file=../buildroot-2022.05.2/output/images/rootfs.ext4,if=none,id=blk1,format=raw \
           -device virtio-blk-device,drive=blk1 \
           -append "console=ttyAMA0 root=/dev/vda" \
           -nographic
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10

      使用root的password登陆进去。

    4. qemu通过u-boot启动kernel

      uboot下载kernel镜像和设备数dtb有两种方式:

      • 可以配置uboot的网络,使用tftp方式下载
      • 使用半主机semihosting的方式加载

      我们这里使用后者,但是需要编译uboot时,在configs/qemu_arm64_defconfig中添加以下配置CONFIG_SEMIHOSTING=y。重新编译后,运行:

      qemu-system-aarch64 \
           -M  virt \
           -cpu cortex-a53 \
           -smp 2 \
           -m 2048M \
           -kernel ../u-boot-master/u-boot \
           -semihosting-config enable=on,target=native \
           -nographic
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

      然后通过semihosting方式添加kernel

      smhload ../linux-5.19.6/arch/arm64/boot/Image
      
      • 1

      最后设置bootargs并启动内核

      setenv bootargs " console=ttyAMA0 root=/dev/vda"
      booti 0x40000000 - 0x43000000
      
      • 1
      • 2

      TODO:这里没有添加成功smhload命令

    5. qemu通过ATF启动u-boot

      拷贝bl1.bin、bl2.bin、bl31.bin到当前目录下,拷贝u-boot.bin到当前目录下并重命名为bl33.bin

      cp ../arm-trusted-firmware-2.7.0/build/qemu/debug/*.bin ./
      cp ../u-boot-master/u-boot.bin ./bl33.bin
      
      • 1
      • 2
      qemu-system-aarch64 \
          -nographic -machine virt,secure=on \
          -cpu cortex-a53 \
          -smp 2 -m 2048 \
          -d unimp \
          -bios bl1.bin \
          -semihosting-config enable=on,target=native
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7

      注意:qemu默认使用FIP方式加载,原始镜像存在memmap中,如果memmap没有镜像,会打印Firmware Image Package header check failed.FIP校验头失败。然后就会使用半主机的方式读取镜像Using Semi-hosting IO,直接半主机方式读取原始镜像到内存地址中(实际上是通过读文件的方式),即不会在校验FIP方式的头这些,因此如果需要FIP方式加载,需要将镜像事先加载到memmap中。

      可以使用gdb的restore命令用来将文件中的数据加载到内容中,使用方法如下,详见第5点

      restore file binary start_addr end_addr
      
      • 1
    6. qemu通过gdb调试目标镜像

      在启动qemu时添加-s –S选项。

      -S:表示QEMU虚拟机会冻结CPU,直到远程的GDB输入相应控制命令
        -s:表示在1234端口接受GDB的调试连接,其与-gdb tcp::1234参数相同

      qemu-system-aarch64 \
          -nographic -machine virt,secure=on \
          -cpu cortex-a53 \
          -smp 2 -m 2048 \
          -d unimp \
          -bios bl1.bin \
          -semihosting-config enable=on,target=native -s -S
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7

      启动GDB,apt-get安装的交叉工具链没有gdb(可以安装gdb-multiarch的gdb),我们这里使用自己下载的工具链。在另一窗口下通过gdb从atf的bl1开始启动:

      ~/toolchain/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-gdb ../arm-trusted-firmware-2.7.0/build/qemu/debug/bl1/bl1.elf
      
      • 1

      gdb通过tcp方式attach到qemu的目标板上

      target remote localhost:1234
      
      • 1

      就开始调试了,执行N,C,B等gdb命令。

      TIPS1:默认ATF编译时开优化,需要打开调试

      CFLAGS='-O0 -gdwarf-2'
      make PLAT=qemu all DEBUG=1
      
      • 1
      • 2

      TIPS2:默认我们开始使用的是bl1的符号表,因此如果要调试bl2,bl31,kernel等,需要在gdb中添加对应的符号表,如下:

      add-symbol-file ../arm-trusted-firmware-2.7.0/build/qemu/debug/bl2/bl2.elf
      
      • 1
    7. qemu使用FIP方式加载ATF

      编译生成FIP包,需要指定BL33镜像的位置,默认会生成fip.bin

      export ARCH=arm64
      export CROSS_COMPILE=aarch64-linux-gnu-
      make PLAT=qemu BL33=../u-boot-master/u-boot.bin all fip DEBUG=1 LOG_LEVEL=50 
      
      • 1
      • 2
      • 3

      下面的命令在build/qemu/debug目录下执行。

      启动qemu

      qemu-system-aarch64 \
          -nographic -machine virt,secure=on \
          -cpu cortex-a53 \
          -smp 2 -m 2048 \
          -d unimp \
          -bios bl1.bin \
          -semihosting-config enable=on,target=native -s -S
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7

      启动gdb调试

      ~/toolchain/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-gdb bl1/bl1.elf
      
      • 1
      • 连接目标板

        target remote localhost:1234
        
        • 1
      • 加载fip.bin到内存

        restore fip.bin binary 0x00040000
        
        • 1

        这里的开始地址和最大大小就是qemu平台配置的

        #define PLAT_QEMU_FIP_BASE		0x00040000
        #define PLAT_QEMU_FIP_MAX_SIZE		0x00400000
        
        • 1
        • 2
      • 全速运行

        c
        
        • 1

      如果开启VERBOSE打印,可以看到每个镜像加载时会打印如下内容

      VERBOSE: FIP header looks OK.
      VERBOSE: Using FIP
      
      • 1
      • 2

    参考

    1. 利用Qemu-4.0虚拟ARM64实验平台
    2. 从零开始搭建qemu调试环境
  • 相关阅读:
    如何应用MBTI职业性格测试来做职业规划
    零配置python日志,安装即用
    MCE | 世界“第一杀手”——心血管疾病
    Frustum PointNets for 3D Object Detection from RGB-D Data(2018)
    算法笔记-归并排序
    每日leetcode[删除排序链表中的重复元素]
    RTC相关实验
    k8s部署
    【验证码逆向专栏】百某网数字九宫格验证码逆向分析
    Python趣味入门9:函数是你走过的套路,详解函数、调用、参数及返回值
  • 原文地址:https://blog.csdn.net/qq_16106195/article/details/126708271