06步:使用u-boot加载内核
6.1 u-boot的存在的必要性
如果是之前玩过实体开发板的朋友,会疑惑一件事情,u-boot去哪了?
这是因为qemu自带bootloader功能,可以直接引导内核,有点类似于自带BIOS系统的电脑主板。
但是嵌入式设备通常是没有这样的条件的,所以我们如果真的要用QEMU完成仿真工作的话,还是得把u-boot加进来。
6.2 u-boot的编译和安装
下载完毕以后,存入目录/home/user/vexpress/u-boot里,老样子,解压,配置编译器,配置BSP,编译,运行
# cd /home/tftpboot
# mkdir uboot
# cd uboot
# wget https://ftp.denx.de/pub/u-boot/u-boot-2022.07-rc3.tar.bz2
# tar -xvf u-boot-2022.07-rc3.tar.bz2
# cd u-boot-2022.07-rc3
# gedit Makefile +272
和前面一样,输入以下内容,配置编译器
ARCH = arm
CROSS_COMPILE = arm-linux-gnueabi-
配置和编译
# make vexpress_ca9x4_defconfig
# make -j 2
出现这个错误是因为没有openssl,装一个问题就解决了
# sudo apt install libssl-dev
这里我们先写一个测试脚本start_uboot.sh脚本
touch start_uboot.sh
chmod 777 start_uboot.sh
gedit start_uboot.sh
输入以下内容:
qemu-system-arm -M vexpress-a9 \
-kernel u-boot \
-nographic \
-m 512M \
运行u-boot:
# ./start_uboot.sh
效果如下图,qemu加载u-boot成功
6.3 u-boot+kernel+根文件系统全真模拟
细心的朋友可能发现了,4.2中我们加载u-boot的方法使用还是-kernel选项,也就是是把u-boot当做内核挂载的。
系统启动不可能同时挂载两个内核启动(只能选择一个启动)
有没有一个可行发方法来模拟呢?有!
u-boot实体机中我们常常采用tftp引导内核,我们也可以在启动u-boot以后,让u-boot通过tftp引导内核
我们需要做两件事情:1.搭建好tftp环境 2.构建网桥,让qemu可以访问,从而让qemu和ubuntu之间可以通过该网桥来访问
6.3.1 安装tftp和相关依赖,设置好路径
sudo apt-get install tftp-hpa tftpd-hpa xinetd uml-utilities bridge-utils
设置tftp配置路径文件:
# sudo vim /etc/default/tftpd-hpa
将下面的内容复制进来
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/home/tftpboot" #该路径即为tftp可以访问到的路径
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="-l -c -s"
配置完以后,创建tftp目录,给最高权限,把内核、设备树、根文件系统、u-boot全部复制到这里,重启tftp服务
# cd /home/tftpboot
# cp /home/tftpboot/uboot/u-boot-2022.07-rc3/u-boot .
# cp /home/tftpboot/kernel/linux-5.10.99/arch/arm/boot/uImage .
# sudo /etc/init.d/tftpd-hpa restart
6.3.2 修改网卡信息,设置桥接
# ifconfig #查看网卡名
# sudo gedit /etc/netplan/01-network-manager-all.yaml #修改网卡名称设置
1.修改/etc/netplan/01/01-network-manager-all.yaml的信息配置,输入以下内容:
network:
version: 2
renderer: networkd
ethernets:
ens37: #这里设置的是你还需要上网的网卡, ifconfig查看
dhcp4: yes
ens38: #这里设置的是br0桥接到的网卡
dhcp4: no
bridges:
br0: #这里设置的是br0网桥
dhcp4: yes
interfaces:
- ens37 #声明br0网桥接入的网卡是ens37
输入sudo netplan apply使其生效,再输入ifconfig查看网卡信息
sudo netplan apply
ifconfig
2.修改/etc/qemu-ifdown信息配置
# sudo gedit /etc/qemu-ifdown
输入以下内容:
#! /bin/sh
# Script to shut down a network (tap) device for qemu.
# Initially this script is empty, but you can configure,
# for example, accounting info here.
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
3.修改/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.33.145 # 这里设置的是网桥br0的地址
再启动修改start.sh再启动(start.sh存入tftpboot中)
# cd /home/user/tftpboot
# touch start.sh
# chmod 777 *
# ls -l
# gedit start.sh
输入启动指令
qemu-system-arm \
-M vexpress-a9 \
-kernel ./u-boot \
-nographic \
-m 512M \
-nic tap,ifname=tap0 \
-append "root=/dev/mmcblk0 rw console=ttyAMA0" \
-sd rootfs.ext3
root登录以后,./start.sh启动u-boot,此时敲击enter键,进入u-boot交互模式,输入以下内容:
setenv ipaddr 192.168.33.144 # 设置u-boot这边的地址(和br0同一网段即可)
setenv serverip 192.168.33.145 # 设置服务器地址(br0网桥的地址)
tftp 0x60003000 uImage # 从tftp下载uImage
tftp 0x60500000 vexpress-v2p-ca9.dtb # 从tftp下载设备树
setenv bootargs "root=/dev/mmcblk0 rw console=ttyAMA0" # 设置根文件系统挂载位置、权限、控制台设备
bootm 0x60003000 - 0x60500000 # 设置启动地址
和前面kernel+busybox一样,挂载成功
6.4 u-boot的一些小修改
6.3中在u-boot中的配置还是很麻烦的,如果是实体机的话因为有在NAND/MMC Flash给了一个分区存参数,使用saveenv指令就能把参数存下来,但是我们这部分还没有把NAND/MMC相关支持完全做好,所以这样是不行的。
每次都要在u-boot这样处理,那也太麻烦了
有更简单的方法吗?
有!我们把u-boot地址、br0地址、内核加载命令bootcmd和根文件系统加载命令bootargs写入u-boot原程序里编译好了再放出来了就可以了。
6.4.1 设置u-boot和br0的IP地址
回到u-boot所在路径,再在vexpress的配置头文件里加入这么几行
# cd /home/tftpboot/uboot/u-boot-2022.07-rc3/
# gedit include/configs/vexpress_common.h +202
输入以下内容:
#define CONFIG_IPADDR 192.168.33.144
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_SERVERIP 192.168.33.145
输入以后,保存再次编译,再把新的u-boot复制到tftp路径
# cd /home/tftpboot/uboot/u-boot-2022.07-rc3
# make -j 2
# cp u-boot /home/tftpboot
# cd /home/tftpboot
6.4.2 设置启动选项
Boot options —> Enable a default value for bootcmd, 输入以下内容
tftp 0x60003000 uImage;tftp 0x60500000 vexpress-v2p-ca9.dtb;setenv bootargs 'root=/dev/mmcblk0 console=ttyAMA0';bootm 0x60003000 - 0x60500000;
6.4.3 编译, 传回tftpboot,再测试
# cd /home/tftpboot/uboot/u-boot-2022.07-rc3
# make -j 2
# cp u-boot /home/tftpboot
# cd /home/tftpboot
# su root
# ./start.sh
用户可以输入reboot重启测试一下,可以发现也是能正常工作的