这里提供相关工具的下载地址
Linux内核下载地址
busybox下载地址
Qemu下载地址
u-boot下载地址
文中使用的版本为Linux-4.9.268、busybox-1.33.0、qemu-5.2.0、u-boot-2021.01-rc4
版本差别不大,应该都没有问题的
一、busybox制作根目录,通过镜像启动linux内核模拟ARM板
1、编译linux内核
编译条件:gcc编译器,交叉编译器
sudo apt install gcc
sudo apt install arm-linux-gnueabi
清除做过的配置
make clean
自定义内核配置,通过空格键选择配置。这里不做修改,采用默认配置,后面可以根据需要再修改。
make menuconfig
如果运行make menuconfig出错,则需要安装如下的支持包
sudo apt-get install lncurses-dev
sudo apt-get install libncurses5-dev
保存退出后会自动生成.config配置文件
然后创建一个脚本输入下面内容,运行即可编译
#! /bin/sh
make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm vexpress_defconfig
make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm
运行命令,开始编译,内容比较多,会花一些时间
sudo sh build.sh
然后会在源码目录下的arch/arm/boot/文件夹下生成镜像Image和zImage
2、编译busybox
进入到busybox目录下,编辑Makefile
搜索如下两个变量,更改成这样
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-gnueabi-
执行下面命令,使得编译器生效
source /etc/profile
修改配置文件
make menuconfig
如果出现没有<curses.h>头文件,尝试安装如下支持包
sudo apt-get install libncurses5-dev
修改配置完成后,make编译
再make install生成默认文件_install
文件内容
记住这个_install文件夹位置,制作根目录的时候会用到
3、编译安装qemu
为了更好的使用qemu,安装前先下载一些安装包
#必要安装包sudo apt-get install git libglib2.0-dev libfdt-dev libpixman-1-dev zlib1g-dev#推荐安装包sudo apt-get install git-emailsudo apt-get install libaio-dev libbluetooth-dev libbrlapi-dev libbz2-devsudo apt-get install libcap-dev libcap-ng-dev libcurl4-gnutls-dev libgtk-3-devsudo apt-get install libibverbs-dev libjpeg8-dev libncurses5-dev libnuma-devsudo apt-get install librbd-dev librdmacm-devsudo apt-get install libsasl2-dev libsdl1.2-dev libseccomp-dev libsnappy-dev libssh2-1-devsudo apt-get install libvde-dev libvdeplug-dev libvte-2.90-dev libxen-dev liblzo2-devsudo apt-get install valgrind xfslibs-dev#额外安装包sudo apt-get install libnfs-dev libiscsi-dev
自带的qemu可能比较老,这里采用安装包的方式安装新版本
解压后进入qemu文件夹
这里选择一种在其他目录安装的方式,比较安全,不会向原目录增加多余的文件
# 在qemu根目录打开终端 # 准备一个本机debug版本 mkdir -p bin/debug/native cd bin/debug/native # 配置 QEMU 并启动构建 ../../../configure --enable-debug #如果提示没有ninja,按照下面进行操作
如果提示没有Ninja,则进行下面的操作
#安装支持包sudo apt install re2c#安装编译ninjagit clone git://github.com/ninja-build/ninja.git && cd ninja./configure.py --bootstrap #如果提示没有python,则sudo apt install python#如果还报错没有c++,则安装sudo apt-get install g++,装完后再次执行上面的命令ls #查看生成的ninja文件cp ninja /usr/bin/ #拷贝ninja文件到/usr/bin/路径下#检查ninja版本ninja --version #如果检查报错就安装sudo apt install ninja-build
错误解决,再回到出错的步骤继续执行
cd .. #回到native目录 ../../../configure --enable-debug
配置完成,然后make编译
这里有8000多行的编译,时间会比较长
安装
sudo make install
# 返回到QEMU根目录cd ../../..
运行./configure --help 可以获得帮助信息
测试qemu编译是否正常,输入命令
bin/debug/native/x86_64-softmmu/qemu-system-x86_64 -L pc-bios
弹出QEMU界面,安装成功。由于还没有制作根目录,所以显示没有设备
根据界面顶端提示,使用ctrl+alt+g退出输入界面
可以用qemu-system-arm -machine help命令来查看所支持的开发板
4、制作启动根目录
自己选择一个地方创建rootfs目录
在rootfs里面创建下面的这些空目录(和busybox的_install文件夹里重复的文件夹也可以不用创建,马上要复制过来)
(1)完善编译环境
先将刚刚busybox里生成的_install文件夹内部的全部内容复制到rootfs文件夹里。
在rootfs文件夹内打开终端
sudo cp -r ../../busybox-1.33.0/_install/* ./
命令里的文件夹路径根据自己的情况来写
当然lib库还是不够的,因为文件系统运行在arm平台,所以还需要arm-linux-gnueabi的库,直接从系统里安装的交叉编译器里复制过来。
sudo cp -p /usr/arm-linux-gnueabi/lib/* ./lib
接着来完善根目录文件
(2)完善设备文件dev内容
从终端进入dev文件夹
-
创建四个串口设备
sudo mknod -m 666 tty1 c 4 1sudo mknod -m 666 tty2 c 4 2sudo mknod -m 666 tty3 c 4 3sudo mknod -m 666 tty4 c 4 4
-
创建控制台
sudo mknod -m 666 console c 5 1
-
创建null
sudo mknod -m 666 null c 1 3
(3)完善配置文件etc内容
从终端进入etc文件夹
-
创建inittab
::sysinit:/etc/init.d/rcS#::respawn:-/bin/sh#::respawn:-/bin/loginconsole::askfirst:-/bin/sh#tty2::askfirst:-/bin/sh::ctrlaltdel:/bin/umount -a -r
-
创建fstab
proc /proc proc defaults 0 0none /dev/pts devpts mode=0622 0 0mdev /dev ramfs defaults 0 0sysfs /sys sysfs defaults 0 0tmpfs /dev/shm tmpfs defaults 0 0tmpfs /dev tmpfs defaults 0 0tmpfs /mnt tmpfs defaults 0 0var /dev tmpfs defaults 0 0ramfs /dev ramfs defaults 0 0
-
创建profile
# /etc/profile: system-wide .profile file for the Bourne shellsecho "-----------------------------------"echo "Mini2440 FileSystem is Ready ..."echo "-----------------------------------"USER="`id -un`"LOGNAME=$USER#PS1='[\u@\h \W]\# ' #显示主机名、当前路径等信息PS1='pymeia@Mini2440:\w # ' PATH=$PATHHOSTNAME=`/bin/hostname`export USER LOGNAME PS1 PATH
-
创建init.d/rcS
#! /bin/shPATH=/bin:/sbin:/usr/bin:/usr/sbin #可执行程序 环境变量export LD_LIBRARY_PATH=/lib:/usr/lib #动态链接库 环境变量/bin/mount -n -t ramfs ramfs /var/bin/mount -n -t ramfs ramfs /tmp/bin/mount -n -t sysfs none /sys/bin/mount -n -t ramfs none /dev/bin/mkdir /var/tmp/bin/mkdir /var/modules/bin/mkdir /var/run/bin/mkdir /var/log/bin/mkdir -p /dev/pts //telnet服务需要/bin/mkdir -p /dev/shm //telnet服务需要#echo /sbin/mdev > /proc/sys/kernel/hotplug//USB自动挂载需要/sbin/mdev -s //启动mdev在/dev下自动创建设备文件节点/bin/mount -aecho "-----------------------------------"echo " welcome to Mini2440 board"echo "-----------------------------------"
-
创建group
root:*:0:daemon:*:1:bin:*:2:sys:*:3:adm:*:4:tty:*:5:disk:*:6:lp:*:7:lpmail:*:8:news:*:9:uucp:*:10:proxy:*:13:kmem:*:15:dialout:*:20:fax:*:21:voice:*:22:cdrom:*:24:floppy:*:25:tape:*:26:sudo:*:27:
-
创建passwd
root::0:0:root:/:/bin/shftp::14:50:FTP User:/var/ftp:bin:*:1:1:bin:/bin:
创建var文件夹,存放日志信息
sudo ln -s /tmp var/locksudo ln -s /tmp var/logsudo ln -s /tmp var/runsudo ln -s /tmp var/tmp
5、qemu启动开发板镜像
制作根文件系统镜像,把rootfs根目录的内容复制到这个镜像中,然后用qemu启动模拟开发板。
方法1
制作磁盘镜像启动方式
(1)制作磁盘镜像img
制作磁盘镜像并格式化
qemu-img create -f raw disk.img 512M #生成512M大小的磁盘镜像mkfs -t ext4 ./disk.img #把磁盘镜像格式化成ext4文件系统
也可以将其打包成mkdisk.sh脚本,方便再次创建
sudo sh mkdisk.sh
#!/bin/shqemu-img create -f raw disk.img 512Mmkfs -t ext4 ./disk.img
(2)复制rootfs内容到磁盘镜像
将rootfs根目录中所有内容复制到磁盘镜像中
mkdir tmpfs #创建一个临时文件夹,文件夹与rootfs同级sudo mount -o loop ./disk.img tmpfs/ #创建挂载点并挂载sudo cp -r rootfs/* tmpfs/ #复制文件到镜像sudo umount tmpfs #卸载
也可以打包起来方便更新磁盘内容
sudo sh update.sh
#!/bin/shsudo mount -o loop ./disk.img tmpfs/sudo cp -r rootfs/* tmpfs/sudo umount tmpfs
更新期间会将rootfs的内容复制到tmpfs,再删除
检查镜像文件信息
file disk.img
(3)启动开发板
不带qemu界面
直接在终端启动,不带lcd界面
sudo sh runnolcd.sh
#! /bin/shqemu-system-arm -M vexpress-a9 -m 512M -dtb ../linux-4.9.268/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -kernel ../linux-4.9.268/arch/arm/boot/zImage -nographic -append "root=/dev/mmcblk0 rw console=ttyAMA0" -sd disk.img
如果遇到拒绝访问的情况,请授予文件访问权限,删掉磁盘重新创建(直接更新不成功)
chmod +x rcSchmod -R 777 init.d/*或者授予etc的所有文件访问权限chmod -R 777 etc/
启动界面如下
带qemu界面
带lcd界面启动方式
sudo sh runlcd.sh
#! /bin/shqemu-system-arm -M vexpress-a9 -m 512M -dtb ../linux-4.9.268/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -kernel ../linux-4.9.268/arch/arm/boot/zImage -append "root=/dev/mmcblk0 rw console=tty0" -sd disk.img
启动界面如下
【注意】:启动终端的命令,里面的路径一定要根据自己创建的文件夹填写正确。启动命令也可以直接在终端输入,但是比较麻烦。
方法2
制作sd根文件系统镜像启动方式
(1)制作sd卡镜像
生成虚拟sd卡并格式化为ext格式
sudo sh mksd.sh
#! /bin/shdd if=/dev/zero of=rootfs.ext3 bs=1M count=32mkfs.ext3 rootfs.ext3
(2)复制内容到sd镜像
将虚拟sd卡挂载到/mnt,拷贝rootfs的所有文件到sd,然后卸载sd
sudo sh update.sh
#! /bin/shmount -t ext3 rootfs.ext3 /mnt/ -o loopcp -r rootfs/* /mntumount /mnt
(3)启动开发板
不带qemu界面
sudo sh runnolcd.sh
#! /bin/shqemu-system-arm -M vexpress-a9 -m 512M -dtb ../linux-4.9.268/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -kernel ../linux-4.9.268/arch/arm/boot/zImage -nographic -append "root=/dev/mmcblk0 rw console=ttyAMA0" -sd rootfs.ext3
带qemu界面
sudo sh runlcd.sh
#! /bin/shqemu-system-arm -M vexpress-a9 -m 512M -dtb ../linux-4.9.268/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -kernel ../linux-4.9.268/arch/arm/boot/zImage -append "root=/dev/mmcblk0 rw console=tty0" -sd rootfs.ext3
6、关闭虚拟开发板
方法一:直接关掉终端
方法二:ctrl +a 放手,然后按x
方法三:打开另一个终端输入
sudo killall qemu-system-arm
二、u-boot启动Linux内核方式,模拟ARM开发板
1、生成uImage内核映像
我们的目的是:uImage文件
生成它的步骤是:编译u-boot生成mkimage--->用mkimage生成uImage
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
这里解释一下uImage:
Linux内核编译(make)之后会生成两个文件,一个Image,一个zImage,其中Image为内核映像文件,而zImage为内核的一种映像压缩文件,Image大约为4M,而zImage不到2M
而uImage是用mkimage工具根据zImage制作而来的,它是uboot专用的映像文件,它是在zImage之前加上一个长度为64字节的“头”,说明这个内核的版本、加载位置、生成时间、大小等信息;其0x40之后与zImage没区别。
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
(1)编译u-boot
修改配置
进入u-boot源码目录,分别进入Makefile和config.mk修改配置
修改顶层Makefile,指定交叉编译器
CROSS_COMPILE ?= arm-linux-gnueabi-
修改顶层config.mk,指定ARM架构
ARCH := arm
编译
#配置开发板make vexpress_ca9x4_defconfig#编译u-bootmake –j4
如果编译出错,缺少如下配置
则安装如下,解决问题
sudo apt install bison flex
如果make -j4报错可能是上面的配置没有起到作用,则尝试如下命令
export CROSS_COMPILE=arm-linux-gnueabi-export ARCH=armmake cleanmake vexpress_ca9x4_defconfigmake -j4
编译完成后如图
测试效果
在u-boot源码路径下,运行u-boot看是否成功
qemu-system-arm -M vexpress-a9 -kernel u-boot -nographic -m 512M
这里由于u-boot还没有uImage镜像,让倒计时结束自动加载会出问题。看到提示后,快速按任意按键,停止自动加载,出现下图,说明编译成功。
(2)拷贝mkimage
编译完u-boot源码,会在tools目录下生成mkimage,用它可以将zImage转变成uImage
把u-boot目录下tools/mkimage 拷贝到/usr/bin目录下,为了可以执行mkimage相关的命令。
如果不拷贝直接执行命令,你会发现/usr/bin缺少文件
除此之外,还可以,直接命令下载,也会再该/usr/bin目录下生成mkimage
sudo apt install u-boot-tools
这种方法下载自带的u-boot-tools不知道会不会出问题,可以尝试尝试。
为nfs服务做准备
再生成uImage前,需要nfs配置的修改,重新编译Linux内核,让内核支持nfs功能,生成新的zImage,然后再转化成uImage
修改配置如下,在Linux内核目录下输入:make menuconfig
进入File system --->
再进入Network File System --->
将带有NFS的都用空格键选上
选中后如图
保存退出
(3)生成uImage(疑问待解决)
方法一:
直接按照以下命令重新编译(待验证,地址也有问题)
export ARCH=arm export CROSS_COMPILE=arm-linux-gnueabi- make vexpress_defconfig make zImage -j8 make modules -j8 make LOADADDR=0x60003000 uImage -j8 make dtbs
方法二:将编译生成的zImage转化成uImage(也是地址问题待解决)
切换到Linux内核目录下,执行下面命令
mkimage -n 'mini2440' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008040 -d arch/arm/boot/zImage arch/arm/boot/uImage
参数说明
-n 'mini2440' #指定镜像名称-A arm #设置为arm架构-O linux #设置操作系统为linux-T kernel #设置镜像类型为kernel-C none #设置压缩类型为none-a 0x30008000 #指定加载地址为0x30008000-e 0x30008040 #执行入口地址为0x30008040-d arch/arm/boot/zImage #指定镜像数据文件路径arch/arm/boot/uImage #最终生成的uImage的路径和文件名称
这里直接在zImage旁边生成uImage
到此uImage镜像生成结束
然后将uImage文件拷贝到tftpboot目录下(这一步也可以后面再一起做),这个文件夹是在配置tftp的时候创建的。
sudo cp ../../linux-4.9.268/arch/arm/boot/uImage ./ #路径根据自己的情况来
2、安装配置nfs服务
在前面我们已经装好了tftp服务器,但还需要安装nfs服务
(1)安装
sudo apt-get install nfs-kernel-server
(2)创建nfs共享目录,设置权限
sudo chmod 777 ./rootfs
(3)添加NFS共享目录路径
vi /etc/exports在/etc/exports添加以下路径/home/pymeia/qemu/ARM/ubootA9/rootfs *(rw,sync,no_subtree_check)其中: rw 可读可写操作 sync 内存和磁盘上的内容保持同步 no_root_squash Linux主机不再将开发板设置为匿名用户,可以操作文件读写 注意:Ubuntu20.04,这个文件里不填这个参数,会报错。exports文件里有参考实例说明,只有三个参数 no_subtree_check 不检查根文件系统子目录文件
(4)重启nfs服务
sudo /etc/init.d/rpcbind restartsudo /etc/init.d/nfs-kernel-server restart或者systemctl restart nfs-kernel-server
(5)检查nfs是否启动正常
sudo showmount -e #显示全部可以挂载的目录sudo /etc/init.d/nfs-kernel-server status #查看nfs服务的当前状态ps -e |grep nfs #看进程中nfs服务是否启动
(6)nfs使用
自己创建一个目录当作nfs目录,然后再/etc/exports中添加路径,可以把你的程序放到这个目录下,通过挂载映射到./mnt。./mnt可以再主机上,也可以在开发板上,方便进行代码的调试。
在本机localhost上挂载nfs目录到./mnt,这样rootfs的内容就映射到了./mnt
sudo mount -t nfs localhost:/home/pymeia/qemu/ARM/ubootA9/rootfs ./mnt/ #这里挂载的目录一定要在/etc/exports里添加,否则挂载无效
卸载后,文件删除
umount ./mnt
同理,在开发板上挂载nfs目录到/mnt(假设主机IP地址为192.168.146.129)
mount -t nfs -o nolock 192.168.146.129:/dev/nfs /mnt其中:-o nolock是去除文件锁,否则会报错
3、安装配置tftp服务
(1)安装tftp
sudo apt-get install tftp-hpa tftpd-hpa xinetd
(2)更改配置文件
sudo cp /etc/default/tftpd-hpa /etc/default/tftpd-hpa_back #备份原始设置sudo gedit /etc/default/tftpd-hpa
填写自己要创建tftpboot文件的路径
(3)创建tftp目录,设置权限
配置好后,到上面填写的路径,创建文件夹,并设置权限
#切换到上面填写的路径sudo mkdir tftpbootsudo chmod 777 tftpboot
(4)重启tftp服务,让其生效
sudo /etc/init.d/tftpd-hpa restart
(5)测试tftp服务是否正常
把需要的文件如u-boot、dtb、uImage等拷贝到tftpboot文件夹(后面u-boot启动要用到)
uImage
cp -r /home/pymeia/qemu/ARM/linux-4.9.268/arch/arm/boot/uImage ./
u-boot
cp -r /home/pymeia/qemu/ARM/ubootA9/u-boot/u-boot ./
vexpress-v2p-ca9.dtb
cp -r /home/pymeia/qemu/ARM/linux-4.9.268/arch/arm/boot/dts/vexpress-v2p-ca9.dtb ./
整理copy.sh
#! /bin/shcp -r /home/pymeia/qemu/ARM/linux-4.9.268/arch/arm/boot/uImage ./cp -r /home/pymeia/qemu/ARM/ubootA9/u-boot/u-boot ./cp -r /home/pymeia/qemu/ARM/linux-4.9.268/arch/arm/boot/dts/vexpress-v2p-ca9.dtb ./
tftp 192.168.146.129 #主机ip可以用ifconfig来查看tftp> get uImage #获取文件,保存到用户名目录下tftp> q #退出tftpps -e | grep "tftp" #查看 tftp 的进程号
可以看到,获取的文件和获取失败的文件都会显示在用户目录下
4、配置qemu和ubuntu网络桥接功能(这一部分,暂时没有搞完)
VMware 需要配置成NAT模式, 在VMware的桥接模式下面,目前qemu无法成功连接网络
VMware也不能设置成静态ip地址,设置成静态ip地址也是无法连接网络
安装桥接依赖包
sudo apt install uml-utilities bridge-utils#bridge-utils 虚拟网桥工具#uml-utilities UML(User-mode linux)工具
查看是否tun设备文件,如果存在说明宿主机的内核支持TAP网络接口
ls /dev/net
如果没有,则要手动创建
sudo mkdir /dev/netsudo mknod /dev/net/tun c 10 200
加载tun模块
sudo /sbin/modprobe tun
非常建议更改重要配置的节点时,及时创建虚拟机快照,方便恢复,已经重装一次,吸取教训了
下面是大雷区,不要乱用,或者在用之前创建还原快照,否则会直接导致Ubuntu 20.04 LTS失去网络,甚至运气差点要重装
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
修改配置文件(重启生效)
sudo gedit /etc/network/interfaces
添加以下内容
# interfaces(5) file used by ifup(8) and ifdown(8)auto loiface lo inet loopbackauto ens33auto br0iface br0 inet dhcpbridge_ports ens33
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
添加qemu有关系统脚本
在/etc/qemu-ifup文件中添加以下内容
#!/bin/shecho sudo tunctl -u $(id -un) -t $1sudo tunctl -u $(id -un) -t $1echo sudo ifconfig $1 0.0.0.0 promisc upsudo ifconfig $1 0.0.0.0 promisc upecho sudo brctl addif br0 $1sudo brctl addif br0 $1echo brctl showbrctl showsudo ifconfig br0 192.168.146.129# 根据自己的实际情况修改 IP地址,注意:uboot 中的 CONFIG_SERVERIP(serverip) 要跟这里一样
在/etc/qemu-ifdown文件中添加以下内容
#!/bin/shecho sudo brctl delif br0 $1sudo brctl delif br0 $1echo sudo tunctl -d $1sudo tunctl -d $1echo brctl showbrctl show
给上面的脚本添加执行权限
sudo chmod +x /etc/qemu*
重启网络使生效
sudo service network-manager restart
u-boot启动
修改u-boot配置文件include/configs/vexpress_common.h
sudo gedit include/configs/vexpress_common.h
#define CONFIG_BOOTCOMMAND \ "tftp 0x60003000 uImage;tftp 0x60500000 vexpress-v2p-ca9.dtb; \ setenv bootargs 'root=/dev/mmcblk0 console=tty0'; \ bootm 0x60003000 - 0x60500000;"#define CONFIG_IPADDR 10.0.2.14#define CONFIG_NETMASK 255.255.255.0#define CONFIG_SERVERIP 192.168.146.129
所有配置完成后,开始建立u-boot启动内核文件
新建启动脚本ubootqemu.sh
#! /bin/shqemu-system-arm \ -M vexpress-a9 \ -kernel u-boot \ -nographic \ -m 512M \ -net nic,vlan=0 -net tap,vlan=0,ifname=tap0 \ -sd rootfs.ext3
未完....问题解决后更新
参考文章链接:
https://blog.csdn.net/u010344264/article/details/82949143
https://zhuanlan.zhihu.com/p/340362172
https://www.jianshu.com/p/8619a6739040
https://www.cnblogs.com/schips/p/12350122.html
https://blog.csdn.net/wxh0000mm/article/details/90056912