Centos7 搭建qemu模拟器模拟arm-vexpress-a9开发板

  • 参考:

整理: 寒水司天

发布: 2018-01-16 23:06

原作: 用Qemu模拟vexpress-a9 by 摩斯电码

  • 转载说明:
    参考以上资料,在CentOS7中搭建成功,感谢摩斯电码等先行的分享。搭建的时候填了一些坑,希望对来者有所帮助,以下是搭建手记。

1、交叉编译器的下载与安装

  • linaro.org, arm-eabi (bare-metal, 裸机), 6.3-2017.05

ARM官方的编译工具链

  • arm.com, arm-eabi (AArch32 bare-metal target, 裸机), 8.2-2019.01
  • AArch32 target with soft float (arm-linux-gnueabi)
  • 2、然后解压缩
# tar jxvf arm-2014.05-29-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2
tar xvf gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabi.tar.xz
  • 3、添加环境变量,假定压缩包所在目录为/home,解压后目录为arm-linux-gnueabi-6。
vim /etc/profile
# 在最下面添加
export PATH=$PATH:/home/arm-linux-gnueabi-6/bin
# 然后更新
source /etc/profile
  • 4、测试是否安装成功
arm-linux-gnueabi-gcc -v

2、qemu的安装

  • 步骤:
# 下载源代码
wget https://download.qemu.org/qemu-3.1.0.tar.xz
tar xvf qemu-3.1.0.tar.xz
# 新建编译目标路径
mkdir build
# 编译
cd qemu-3.1.0
./configure --target-list=arm-softmmu --audio-drv-list= --prefix=/root/qemu/build  # 配置qemu,支持模拟arm架构下的全部单板
# ./configure --prefix=/root/xxx/build
make -j8
make install

# 说明:
$./configure --enable-kvm --enable-debug --enable-vnc --enable-werror  --target-list=arm-softmmu --audio-drv-list=
# configure脚本用于生成Makefile,其选项可以用./configure --help查看。这里使用到的选项含义如下:
# --enable-kvm:编译KVM模块,使QEMU可以利用KVM来访问硬件提供的虚拟化服务。
# --enable-vnc:启用VNC。
# --enalbe-werror:编译时,将所有的警告当作错误处理。
# --target-list:选择目标机器的架构。默认是将所有的架构都编译,但为了更快的完成编译,指定需要的架构即可。

3、uboot安装

参考:

wget http://ftp.denx.de/pub/u-boot/u-boot-2018.09.tar.bz2
  • 2)、解压源文件
tar jvxf u-boot-2018.01.tar.bz2 -C xxxx  (xxx为需要解压的目录)
  • 3)、进入U-Boot 源文件目录,然后执行:
# export CROSS_COMPILE=arm-none-eabi-
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabi-
# 要求bison等
yum install bison flex
# 编译
make vexpress_ca9x4_defconfig
make
# 或执行如下2个步骤
# make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm vexpress_ca9x4_defconfig
# make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm

编译完成后,如果目录下生成 u-boot 文件,则说明编译成功。

  • 4)、在U-Boot源码目录下编写脚本 run.sh
qemu-system-arm -M vexpress-a9 -nographic -m 512M -kernel u-boot

然后 chmod +x run.sh 增加文件执行权限。

  • 5)、最后执行./run.sh,可以看到启动了bootloader,但是会提示没有映像文件
smc911x: MAC 52:54:00:12:34:56
Wrong Image Format for bootm command
ERROR: can't get kernel image!
=>

Ctrl+a,X 退出

4、编译内核

  • Git clone
git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
  • 直接下载
wget https://mirrors.tuna.tsinghua.edu.cn/kernel/v3.x/linux-3.18.135.tar.xz
  • 1)、从arch/arm/configs下找到需要编译内核的配置文件vexpress_defconfig,复制到源码根目录下
  • 2)、执行命令
# export CROSS_COMPILE=arm-none-eabi-
# export ARCH=arm
make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm  vexpress_defconfig  # 生成vexpress开发板的config文件
make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm  zImage
make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm  modules
make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm  dtbs
  • 3)、编译后生成 在 arch/arm/boot 目录下生成 zImage 文件,则说明编译成功。
  • 测试
qemu-system-arm -M vexpress-a9 -m 512M -kernel zImage -nographic -append "console=ttyAMA0"
  • 内核启动参数中的console=参数应该填上哪个tty?
  • 参考:
  • 解决: 因为不同单板串口驱动类型不尽相同,创建的tty设备名当然也是不相同的。那vexpress单板的tty设备名是哪个呢? 其实这个值可以从生成的.config文件CONFIG_CONSOLE宏找到。
  • 4)、关于内核版本
  • 参考:
  • 说明: 发现主线上3.18版本号和后面版本号的代码,使用这样的搭建方法执行不起来。眼下未查明问题的根因。假设读者想高速搭建成功。建议选用3.16版本号的内核进行搭建。
  • 5)、笔者用5.4版本的arm-none-eabi-编译3.1.16版本的内核时,报如下错误
include/linux/compiler-gcc.h:106:30: fatal error: linux/compiler-gcc6.h: No such file or directory
#include gcc_header(__GNUC__)
  • 参考:
# 原因是因为我使用的交叉编译工具链版本太高(6.2.1版本)导致,先在内核代码根目录下搜索compiler-gcc*
./include/linux/compiler-gcc3.h 
./include/linux/compiler-gcc5.h 
./include/linux/compiler-gcc.h 
./include/linux/compiler-gcc4.h
# 支持的版本有3、4、5,在Linaro官网上下载5版本的交叉编译工具链即可解决问题。
  • 笔者用gcc-linaro-6.3.1版本的arm-linux-gnueabi编译3.1.16时也报告上述问题,编译3.18.135版本未有报告上述问题。

5、编译busybox

  • 1)、从https://busybox.net/downloads/下载busybox
  • 2)、进入 Busybox 源文件目录下执行 make menuconfig,如果报错,则yum list ncurses,然后安装列出来的东西
Busybox Setting -> Build options 
  -> Build Busybox as a static binary (no shared libs)    # 选中 静态编译。
  -> Cross Compiler prefix                                # 交叉编译器配置(arm-linux-gnueabi-,可make命令带入)
  -> Installation options -> BusyBox installation prefix  # 默认目标位置(若不指定,需手动移到rootfs;若已有rootfs,可指定rootfs位置<推荐,自动完成>)

注意:若不选中“Build Busybox as a static binary (no shared libs)”,起qemu运行时,将会报“kernel panic”错误!

  • 3)、编译
make distclean   # 清除原有配置
make menuconfig  # 配置命令选项
make CROSS_COMPILE=arm-linux-gnueabi-
make CROSS_COMPILE=arm-linux-gnueabi- install   # 在_install 目录下生成编译文件: bin sbin linuxrc usr 等
  • 4)、问题
  • 用arm-none-eabi-编译busybox时,报找不到curses.h错误
# make menuconfig
HOSTCC  scripts/basic/fixdep
HOSTCC  scripts/basic/split-include
HOSTCC  scripts/basic/docproc
HOSTCC  scripts/kconfig/conf.o
HOSTCC  scripts/kconfig/kxgettext.o
HOSTCC  scripts/kconfig/mconf.o
HOSTCC  scripts/kconfig/zconf.tab.o
HOSTLD  scripts/kconfig/mconf
HOSTCC  scripts/kconfig/lxdialog/checklist.o
  In file included from scripts/kconfig/lxdialog/checklist.c:24:0:
  scripts/kconfig/lxdialog/dialog.h:31:20: 致命错误:curses.h:没有那个文件或目录
  #include CURSES_LOC
  • 解决:

6、制作根文件系统

dd if=/dev/zero of=a9rootfs.ext3  bs=1M  count=32
  • 2)、格式化
mkfs.ext3 a9rootfs.ext3
  • 3)、创建根文件系统目录
mkdir rootfs
  • 4)、拷贝busybox下的文件
cp busybox/busybox-1.26.2/_install/* -r rootfs/
  • 5)、拷贝交叉编译器的lib
mkdir rootfs/lib/
cp -P /xxx/arm-linux-gnueabi/lib/* rootfs/lib/
  • 6)、创建终端设备
mkdir rootfs/dev/
mknod rootfs/dev/tty1    c 4 1
mknod rootfs/dev/tty2    c 4 2
mknod rootfs/dev/tty3    c 4 3
mknod rootfs/dev/tty4    c 4 4
mknod rootfs/dev/console c 5 1
mknod rootfs/dev/null    c 1 3
  • 7)、创建必要目录
mkdir -p rootfs/proc/
mkdir -p rootfs/sys/
mkdir -p rootfs/tmp/
mkdir -p rootfs/root/
mkdir -p rootfs/var/
mkdir -p rootfs/mnt/
  • 8)、创建临时目录并与空白文件映射,目的是将根文件系统拷贝进去
mkdir tmpfs
mount -t ext3  a9rootfs.ext3  tmpfs/ -o  loop 
cp -r rootfs/* tmpfs/
umount tmpfs
  • 0)、以上步骤的脚本
    建立一个目录,将zImage,vexpress-v2p-ca9.dtb,_install目录拷贝在一个目录下
# 打开脚本文件
vim 
# 粘贴如下内容
rm -rf rootfs
rm -rf tmpfs
rm -f  a9rootfs.ext3

mkdir rootfs
cp ../busybox/busybox-1.26.2/_install/* rootfs/ -raf  # 与你的busybox的目录有关
mkdir -p rootfs/proc/
mkdir -p rootfs/sys/
mkdir -p rootfs/tmp/
mkdir -p rootfs/root/
mkdir -p rootfs/var/
mkdir -p rootfs/mnt/

cp -arf ~/xxx/arm-linux-gnueabi-6/lib/lib rootfs/     # 与你的arm-linux-gnueabi-的目录有关 
rm rootfs/lib/*.a
arm-linux-gnueabi-strip rootfs/lib/*

mkdir -p rootfs/dev/
mknod rootfs/dev/tty1    c 4  1
mknod rootfs/dev/tty2    c 4  2
mknod rootfs/dev/tty3    c 4 3
mknod rootfs/dev/tty4    c 4 4
mknod rootfs/dev/console c 5 1
mknod rootfs/dev/null    c 1 3

dd if=/dev/zero of=a9rootfs.ext3  bs=1M  count=32
mkfs.ext3 a9rootfs.ext3

mkdir -p tmpfs
mount -t ext3  a9rootfs.ext3  tmpfs/ -o  loop
cp -r rootfs/*  tmpfs/
umount tmpfs

7、启动

# 拷贝kernel文件到a9rootfs.ext3所在目录,以便执行
cp -r ../kernel/linux-3.18.135/arch/arm/boot/ .
# 执行
qemu-system-arm  -nographic -sd a9rootfs.ext3 -M vexpress-a9 -m 512M -kernel zImage -dtb ./dts/vexpress-v2p-ca9.dtb -append "init=/linuxrc root=/dev/mmcblk0 rw rootwait earlyprintk console=ttyAMA0"  
qemu-system-arm  -serial stdio -sd a9rootfs.ext3 -M vexpress-a9 -m 512M -kernel zImage -dtb ./dts/vexpress-v2p-ca9.dtb -append "init=/linuxrc root=/dev/mmcblk0 rw rootwait earlyprintk console=ttyAMA0"

8、注意

  • 1)、以上在编译前请确保export ARCH=arm ;export CROSS_COMPILE=arm-linux-gnueabi-
  • 2)、若报错,一般是某些库没有包含,自行百度或google

9、问题

  • 1)、audio: Could not init `oss’ audio driver
  • 解决: [QEMU下虚拟机内的声卡模拟方法总结 ()] ()