从0开始使用QEMU模拟ARM开发环境之uboot通过tftp加载uImage并指定nfs挂载根文件系统

从0开始使用QEMU模拟ARM开发环境系列一览表

从0开始使用QEMU模拟ARM开发环境系列一览表

uboot通过tftp加载uImage

为了通过 tftp 加载有关的文件到指定的内存地址,需要先完成下面2个步骤。

  1. 在主机搭建tftp服务器

  2. QEMU网络功能配置

主机搭建tftp服务器

安装

sudo apt-get install tftp-hpa tftpd-hpa -y

配置

sudo vi /etc/default/tftpd-hpa
或者
sudo gedit /etc/default/tftpd-hpa

根据需求进行修改即可

#/etc/default/tftpd-hpa
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/home/leacock/tftpboot" # tftpd-hpa的服务目录 /tftpboot
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="-l -c -s" # 这里是选项,-c是可以上传文件的参数,-s是指定tftpd-hpa服务目录,上面已经指定

重启服务

sudo service tftpd-hpa restart # stop ,start

测试

tftp 127.0.0.1

QEMU网络功能配置

为了 让 QEMU 能够与主机 建立网络连接,采用桥接的网络连接与Host通信(需要主机内核tun/tap模块支持)

QEMU中的网络,包含两部分的内容

  1. 客户机使用的虚拟网络设备
  2. 和上述虚拟设备通信的网络后端,这些后端负责把虚拟设备的数据包发到宿主机的网络中

QEMU 两种上网方式(不同的网络后端):

user mode network :

这种方式实现虚拟机上网很简单,类似vmware里的nat,qemu启动时加入-user-net参数,虚拟机里使用dhcp方式,即可与互联网通信,但是这种方式虚拟机与主机的通信不方便。

tap/tun network :

这种方式要比user mode复杂一些,但是设置好后 虚拟机<–>互联网 虚拟机<–>主机 通信都很容易

这种方式设置上类似vmware的host-only,qemu使用tun/tap设备在主机上增加一块虚拟网络设备(tun0),然后就可以象真实网卡一样配置它。

TAP后端

QEMU的TAP后端利用宿主机的TAP设备,为客户机提供完整的桥接网络支持,如果外部需要使用标准端口连接到客户机, 或者多个客户机需要相互通信,可以使用该方式。 TAP后端还具有以下优势:

  1. 非常好的性能
  2. 可以配置以支持各种网络拓扑

但是,你需要在宿主机上进行网络拓扑的配置,而且各种系统的配置不同。

主机安装工具包:

sudo apt-get install uml-utilities bridge-utils -y

使用TAP后端前,需要确认你的宿主机的内核支持TAP网络接口: /dev/net/tun 文件存在则说明支持。

ls /dev/net
输出
tun

如果没有这样的文件,可以尝试手工创建:

sudo mkdir /dev/net
sudo mknod /dev/net/tun c 10 200
sudo /sbin/modprobe tun

修改网络配置文件(重启生效)

sudo vi /etc/network/interfaces
或者
sudo gedit /etc/network/interfaces

添加以下内容,注意 根据自己的实际情况 修改 bridge_ports

auto br0
iface br0 inet dhcp
bridge_ports ens33
# ens33 通过ifconfig 查看的网卡

添加qemu有关系统脚本

/etc/qemu-ifup 文件中添加以下内容

#!/bin/sh

echo sudo tunctl -u $(id -un) -t $1

sudo tunctl -u $(id -un) -t $1
echo sudo ifconfig $1 0.0.0.0 promisc up
sudo ifconfig $1 0.0.0.0 promisc up
echo sudo brctl addif br0 $1
sudo brctl addif br0 $1
echo brctl show
brctl show

sudo ifconfig br0 192.168.100.101
# 根据自己的实际情况修改 IP地址,注意:uboot 中的 CONFIG_SERVERIP(serverip) 要跟这里一样 见后面

/etc/qemu-ifdown 文件中添加以下内容

#!/bin/sh

echo sudo brctl delif br0 $1
sudo brctl delif br0 $1
echo sudo tunctl -d $1
sudo tunctl -d $1
echo brctl show
brctl show

给上面的脚本添加执行权限

sudo chmod +x /etc/qemu*

重启网络使生效

sudo service networking restart

ifconfig 查看

在这里插入图片描述

如下命令测试功能,下发后可以在mnt文件夹中看到/nfsroot/rootfs内容

sudo mount -t nfs 192.168.100.101:/nfsroot/rootfs /mnt -o proto=tcp -o nolock

测试完成注意 umount

uboot 修改和重新编译

修改uboot代码

回到u-boot-master 根目录 include/configs/vexpress_common.h中加入相应的宏定义

// 根据自己的实际情况修改对应的地址
#define CONFIG_IPADDR   192.168.100.100
#define CONFIG_NETMASK  255.255.255.0
#define CONFIG_SERVERIP 192.168.100.101
/* 指定启动文件为uImage */
#define CONFIG_BOOTFILE "uImage"
/* 指定启动命令 */
#define CONFIG_BOOTCOMMAND  "tftp 0x60003000 uImage;tftp 0x60500000 vexpress-v2p-ca9.dtb; setenv bootargs'root=/dev/mmcblk0 console=ttyAMA0'; bootm 0x60003000 - 0x60500000"

实际上,CONFIG_BOOTCOMMAND的值会在uboot启动以后自动执行,相当于在下载模式输入下面的指令

tftp 0x60003000 uImage
tftp 0x60500000 vexpress-v2p-ca9.dtb
setenv bootargs'root=/dev/mmcblk0 console=ttyAMA0'
bootm 0x60003000 - 0x60500000

重新编译uboot
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
# make clean && make vexpress_ca9x4_defconfig # 不需要改配置
make -j6
仿真uboot

qemu-system-arm -M vexpress-a9 -m 256 -kernel u-boot -nographic

在这里插入图片描述

启动后print打印看是否有

=> print
...
arch=arm

bootcmd=tftp 0x60003000 uImage;tftp 0x60500000 vexpress-v2p-ca9.dtb; setenv bootargs'root=/dev/mmcblk0 console=ttyAMA0'; bootm 0x60003000 - 0x60500000
...
bootfile=uImage
...
ipaddr=192.168.100.100
...
netmask=255.255.255.0
...
serverip=192.168.100.101

在这里插入图片描述

指定编译 kernel 与 dtb

回到 linux-5.4.95 根目录

LOADADDR(运行地址) 和uboot的启动加载位置一致 , 见 修改uboot代码

export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-

make dtbs -j6
make uImage LOADADDR=0x60003000 -j6

如果出现如下问题

在这里插入图片描述

执行命令 sudo apt-get install u-boot-tools 安装tools 后,再执行

在这里插入图片描述

进行仿真

uImagevexpress-v2p-ca9.dtb 放到tftp目录下,vexpress-v2p-ca9.dtbarch/arm/boot/dts/

在这里插入图片描述

tftp 目录中文件如下

在这里插入图片描述

回到u-boot-master 根目录 ,拷贝 文件 a9rootfs.ext3 到u-boot-master 根目录下,在其中执行命令

sudo qemu-system-arm -M vexpress-a9 -m 256 -kernel u-boot -nographic -net nic,macaddr=00:16:3e:00:00:01 -net tap -sd ./a9rootfs.ext3

在这里插入图片描述

会卡住提示

—[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0) ]—

这需要 uboot指定nfs挂载根文件系统 见下

配置uboot指定nfs挂载根文件系统

在内核配置编译时需要Linux内核对nfs文件系统的支持

开启nfs服务(开发机)
sudo apt-get install nfs-kernel-server -y

配置好 /etc/exports

sudo gedit /etc/exports
添加 
/nfsroot/rootfs *(rw,async,no_root_squash,no_subtree_check)
创建目录
sudo mkdir -p /nfsroot/rootfs

重启nfs-kernel-server或者重启机器

sudo service nfs-kernel-server restart 
uboot修改bootargs

回到u-boot-master 根目录 include/configs/vexpress_common.h中修改

备份好bootargs

 原 
#define CONFIG_BOOTCOMMAND  "tftp 0x60003000 uImage;tftp 0x60500000 vexpress-v2p-ca9.dtb; setenv bootargs'root=/dev/mmcblk0 console=ttyAMA0'; bootm 0x60003000 - 0x60500000"
 修改为
 #define CONFIG_BOOTCOMMAND  "tftp 0x60003000 uImage;tftp 0x60500000 vexpress-v2p-ca9.dtb;setenv bootargs 'root=/dev/nfs nfsroot=${serverip}:/nfsroot/rootfs,tcp rw ip=${ipaddr}:${serverip}:${gatewayip}:${netmask} ::eth0:on init=/linuxrc console=ttyAMA0,115200';bootm 0x60003000 - 0x60500000"
需要替换具体值
 #define CONFIG_BOOTCOMMAND  "tftp 0x60003000 uImage;tftp 0x60500000 vexpress-v2p-ca9.dtb;setenv bootargs 'root=/dev/nfs nfsroot=192.168.100.101:/nfsroot/rootfs,tcp rw ip=192.168.100.100:192.168.100.101:192.168.100.1:255.255.255.0::eth0:on init=/linuxrc console=ttyAMA0,115200';bootm 0x60003000 - 0x60500000"

注意 没有换行

注:
${ipaddr}     开发板本身的地址
${serverip}    tftp及nfs目录所在系统的地址
${gatewayip}    网关
${netmask}      子网掩码
 
 
 
 
其中:
root=/dev/nfs
    /dev/nfs并非真的设备,而是一个告诉内核要通过网络取得根文件系统。
 
nfsroot=<server-ip>:<root-dir>
    参数nfsroot这个参数告诉内核以哪一台机器的哪个目录以及哪个网络文件系统选项作为根文件系统使用。
    <server-ip>  指定网络文件系统服务端的IP地址。如果没有指定定,则使用nfsaddrs变量指定的值。
    <root-dir>    服务端上要作为根文件系统要挂载的目录名称。
 
ip=<my-ip>:<serv-ip>:<gw-ip>:<netmask>:<name>:<dev>:<auto>
    参数ip设定网络通讯所需的各种网络接口地址。
    如果没有给定这个参数,则内核核会试着使用反向地址解析协议或是启动协议(BOOTP)以找出这些参数。
    <ipaddr>         客户端的IP地址。
    <serverip>       网络文件系统服务端的IP地址。
    <gatewayip>   网关(gateway)的IP地址。
    <netmask>      本地网络的网络掩码。如果为空白,则掩码由客户端的IP地址导出。
    <name>          客户端的名称。如果空白,则使用客户端IP地址的ASCII标记值。
    <dev>             要使用的网络设备名称。如果你只有一个设备,那么你可以不管它。一般指定为eth0。
    <auto>            用以作为自动配置的方法。,可以是on可以是off
 
init=/linuxrc 指定初始化文件
 
console=ttySAC2,115200 控制台选择

然后 重新编译uboot

export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
# make clean && make vexpress_ca9x4_defconfig # 不需要改配置
make -j6

拷贝 busybox 制作rootfs 到 nfs挂载 的目录中,也就是下图中所有文件拷贝到 /nfsroot/rootfs

在这里插入图片描述
当然你也可以直接使用 Ubuntu 官网下载的文件系统,不过u-boot-master 根目录 include/configs/vexpress_common.h中加入相应的宏定义需要修改一下,去掉 `init=/linuxrc

修改为:

#define CONFIG_BOOTCOMMAND  "tftp 0x60003000 uImage;tftp 0x60500000 vexpress-v2p-ca9.dtb;setenv bootargs 'root=/dev/nfs nfsroot=192.168.100.101:/nfsroot/rootfs,tcp rw ip=192.168.100.100:192.168.100.101:192.168.100.1:255.255.255.0::eth0:on  console=ttyAMA0,115200';bootm 0x60003000 - 0x60500000"

启动模拟器运行会报错

在这里插入图片描述

[ TIME ] Timed out waiting for device dev-ttyAMA0.device. 解决方案

参见 https://blog.csdn.net/hushui/article/details/103764254

ARM 默认 ttyAMA0串口需要 ,Ubuntu 需要同时使能 ttyAMA0 and default tty1 , 在Ubuntu 根文件系统根目录中执行

sudo ln -s /lib/systemd/system/getty@.service etc/systemd/system/getty.target.wants/getty@ttyAMA0.service
或者
sudo cp -d getty@tty1.service getty@ttyAMA0.service

然后反查

在这里插入图片描述

重新启动模拟器运行成功进入系统,但要密码

删除登录密码如下图,修改 /etc/shadow

在这里插入图片描述

重新启动,登录 root

在这里插入图片描述

启动模拟器

回到u-boot-master 根目录 ,在其中执行命令

sudo qemu-system-arm -M vexpress-a9 -m 256 -kernel u-boot -nographic -net nic,macaddr=00:16:3e:00:00:01 -net tap

如果出现 下面报错

end Kernel panic - not syncing: Requested init /linuxrc failed (error -2).

原因1,可能是 基于 busybox 制作rootfs并仿真 是 未勾选 Settings-> [*] Build static binary (no shared libs) 重新 制作rootfs就行

原因2,busybox 制作rootfs 时拷贝库文件有缺失

系统成功启动,测试 nfs挂载根文件系统是否成功,在挂载目录中创建新文件(我在 /nfsroot/rootfs 创建名为 nft_mount_test.txt 的文件) 然后 在启动的系统中 查看

在这里插入图片描述

QEMU参数

参见: qemu参数大全

希望我的文章对于大家有帮助,由于个人能力的局限性,文中可能存在一些问题,欢迎指正、补充!

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
下面是在QEMU模拟ARM开发板并使用U-Boot引导系统镜像进行系统移植的详细步骤: 1. 安装QEMU:首先,你需要安装QEMU模拟器。据你的操作系统选择适合的版本,并按照官方文档的指导进行安装。 2. 获取ARM开发板固件:你需要获取一个ARM开发板的固件镜像,这包括U-Boot引导加载器和操作系统映像文件。通常可以从开发板供应商或开源社区获取这些镜像。 3. 创建虚拟机:打开终端或命令提示符窗口,运行以下命令来创建一个虚拟机实例,其中`path_to_uboot_image`是指向U-Boot镜像文件的路径,`path_to_kernel_image`是指向内核映像文件的路径,`path_to_rootfs_image`是指向文件系统映像文件的路径: ``` qemu-system-arm -M <machine> -m <memory> -kernel <path_to_uboot_image> -dtb <path_to_dtb_file> -append "console=ttyAMA0" -sd <path_to_rootfs_image> ``` 其中,`machine`是指定模拟ARM开发板型号(例如`versatilepb`),`memory`是指定虚拟机的内存大小(例如`256M`),`path_to_dtb_file`是指向设备树二进制文件(DTB)的路径。 4. 启动虚拟机:运行上述命令后,QEMU将启动虚拟机,并加载U-Boot引导加载器。你将在终端或命令提示符窗口中看到U-Boot的输出信息。 5. 进行系统移植:一旦虚拟机启动成功,你可以在U-Boot的命令行界面中输入命令来配置和加载操作系统。你可能需要设置环境变量、加载内核映像和设备树,以及设置启动参数等。 6. 测试和调试:完成系统移植后,你可以在虚拟机中进行测试和调试。你可以运行应用程序,测试系统的功能和性能。 需要注意的是,U-Boot的配置和使用可能因不同的开发板和需求而有所不同。确保阅读U-Boot的文档以了解更多配置和使用细节。 希望这些详细步骤能够帮助你在QEMU模拟ARM开发板,并使用U-Boot引导系统镜像进行系统移植。如果你有任何进一步的问题,请随时提问。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨1024

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值