Qemu Busybox U-boot

前言

  • 安装和配置环境: Ubuntu 18.04.4
  • 时间: 2020.10
安装u-boot-tools
  1. 介绍: 用来生成适应u-boot引导的镜像文件
  2. 命令
sudo apt install u-boot-tools
安装vim和gedit

1 介绍: 编辑文本工具
2. 命令

sudo apt install vim gedit

安装交叉编译器工具

  1. 介绍: 交叉编译是在一种计算机环境中编译程序,在另外一种环境下运行。或者说在一个平台上编译生成在另外一个平台上运行的可执行代码。
  2. ABI: 二进制应用程序接口(Application Binary interface(ABI) for the ARM Architecture)在计算机中,应用二进制接口描述应用程序和操作系统之间或其他应用程序的低级接口,涵盖了数据类型的大小、布局和对齐,调用约定。
  3. EABI: 嵌入式ABI
  4. 早期u-boot和linux编译可能使用的都是不是一个arm-linux-gcc版本。arm-none-gnueabi-linux比arm-linux-gcc在可移植性和兼容性上更好。
  5. 命令
sudo apt install gcc-arm-linux-gnueabi
sudo apt install g++-arm-linux-gnueabi
  1. 查看版本号
arm-linux-gnueabi-gcc -v
arm-linux-gnueabi-g++ -v
  1. 验证
  • 在当前文件夹下面编写一个Hello.c的文件
arm-linux-gnueabi-gcc Hello.c -o Hello // 编译
readelf -h Hello
  • 输出结果Machine 是ARM类型
    在这里插入图片描述

安装Qemu和内核

方法一自动安装
sudo apt install qemu
qemu-img -V // 查看版本
方法二手动编译
  1. 安装
2. 安装依赖包
sudo apt install zlib1g-dev libglib2.0-0 libglib2.0-dev libsdl1.2-dev libpixman-1-dev libfdt-dev

3. 下载QEMU源码
git clone git://git.qemu-project.org/qemu.git
4. 切换稳定版本
git branch
git checkout v2.7.0
5. 编译配置
./configure --target-list=arm-softmmu --audio-drv-list=
6. 编译安装
make 
make install
  1. 查看
qemu-system-  // 按tab键 查看qemu支持的cpu架构
qemu-system-arm --version // 查看arm架构cpu的版本
qemu-system-arm -M help // 查看支持的开发版本
ARM express 开发板介绍
  1. Vexpress 系列开发板
  • 全称: versatile express family, ARM 公司自己推出的开发板
  • 主要用于SOC厂商设计,验证和测试自己的SOC芯片
  • 采用主板+子板设计,主板提供各种外围接口,子板提供CPU运算
  1. Express 系列支持的CPU
  • Cortex-A9: 处理器子板 Express A9x4(V2P-CA9x4)
  • Cortex-A5: 处理器子板 Express A5x2(V2P-CA5x2s)
  • Cortex-R5:
  • Cortex-A15: 处理器子板 Express A15x2(V2P-CA15x2)
Linux内核下载安装编译
  1. Linux内核下载链接
  2. 解压并进入文件夹中
tar -xvf linux-5.8.12.tar.xz
cd linux-5.8.12
  1. 修改Makefile
vim Makefile
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-gnueabi-
  1. 编译内核、模块、dtb文件
// 编译内核
make vexpress_defconfig
make zImage -j6

// 编译内核模块
make modules

// 编译dtb文件
make dtbs
// dtbs 让编译后的内核脱离主板的限制,不同开发板的配置都在自己的dtbs文件中

// ./arch/arm/boot/
  1. 验证
// linux-5.8.12e文件夹虾执行

qemu-system-arm -M vexpress-a9 -m 512M -kernel arch/arm/boot/zImage -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic -append "console=ttyAMA0"

// -M vexpress-a9 选择使用开发板
// -m 512M 选择内存大小
// -kernel arch/arm/boot/zIamge 选择内核镜像位置
// -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb 选择dtb文件
// -nographic 非图形化显示
// -append "console=ttyAMA0" 虚拟开发板的串口
  • 由于没有制作根文件系统,不能继续执行
  • 退出
ps -a // 查找叫qemu-system-arm进程的PID
kill PID
  1. 制作启动脚本
touch boot.sh
sudo chmod 755 boot.sh
vim boot.sh

// output 
qemu-system-arm -M vexpress-a9 -m 512M -kernel arch/arm/boot/zImage -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic -append "console=ttyAMA0"

// 注意路径问题,可能需要修改

//运行
./boot.sh

使用busybox制作根文件系统

  1. 介绍:
  • 文件系统: 对存储设备上数据进行组织的机制
  • 为什么使用文件系统:
    一切皆文件;
    用户与操作系统进行交互的主要工具: 文件系统调用;
    用户和底层存储的接口;
  • 根文件系统:
    linux 内核启动后第一个挂载的文件系统
    主要由基本的shell命令,各种库,字符设备,配置脚本组成;
    提供了根目录/
    RFS可以放在: nor/nand flash, SD卡,磁盘, 网络空间;
  • 什么是busybody?
    一个集成100多个的linux 常用命令和工具的软件;
    一个适合制作嵌入式文件系统的软件工具;
制作Shell命令
  1. 下载并解压
tar -xvf busybox-1.32.0.tar.bz2 // 解压
cd busybox-1.32.0
  1. 修改Makefile
vim Makefile

// modify
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-gnueabi- 
  1. 配置
make defconfig
make menuconfig

// setting -> build options -> 选上 Build static binary (no shared libs)
  1. 编译 & 安装
make -j4
make install
制作根文件系统
  1. 制作一个目录rootfs,位置自定义
mkdir rootfs
  1. 命令
// 拷贝制作bin sbin usr等
cp -r 你的busybox路径/_install/* 你的rootfs/
如
cp -r ~/Desktop/busybox-1.32.0/_install/* ~/Desktop/rootfs/
// 我的busybox和rootfs都放在桌面

cd rootfs
mkdir lib // 根文件系统的库

// 切换到正确的位置
// 制作lib 拷贝arm的库,从交叉编译器中拷贝
cp -p /usr/arm-linux-gnueabi/lib/* rootfs/lib/

cd rootfs
mkdir dev
cd dev
// 创建结点 sudo权限
mknod -m 666 tty1 c 4 1
mknod -m 666 tty2 c 4 2
mknod -m 666 tty3 c 4 3
mknod -m 666 tty4 c 4 4

// 创建工作台结点
mknod -m 666 console c 5 1

// null 结点 垃圾桶
mknod -m 666 null c 1 3


// 制作 etc目录(可选择不做)
mkdir etc
cd etc
mkdir init.d
cd init.d
touch rcS
sudo chmod a+s rcS
vim rcS

// rcs 编辑的内容(自定义)(此行不复制)
echo
echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
echo
echo "Welcome to A9 vexpress borad"
echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
// rcs内编辑(此行不复制)
制作SD卡文件系统镜像
  1. dd命令虚拟生成SD卡
// 注在那执行下一句命令,就在那生成根文件系统文件rootfs.ext3

dd if=/dev/zero of=rootfs.ext3 bs=1M count=32
  1. 格式化SD卡
mkfs.ext3 rootfs.ext3
  1. 挂载 & 卸载SD卡
sudo mount -t ext3 rootfs.ext3 /mnt/ -o loop
ls /mnt/
// output
// lost+found

// 将制作好的根文件系统拷贝在/mnt中
sudo cp -r rootfs/* /mnt/
ls /mnt/

// 卸载
sudo umount /mnt/
启动内核,挂载rootfs
  1. 修改原先制作的boot.sh脚本(boot.sh 和 linux-5.8.12是同级的)
qemu-system-arm \
	-M vexpress-a9 \
	-m 512M \
	-kernel linux-5.8.12/arch/arm/boot/zImage \
	-dtb  linux-5.8.12/arch/arm/boot/dts/vexpress-v2p-ca9.dtb \
	-nographic \
	-append "root=/dev/mmcblk0 rw console=ttyAMA0" \
	-sd rootfs.ext3
  1. 图像化显示
qemu-system-arm \
	-M vexpress-a9 \
	-m 512M \
	-kernel linux-5.8.12/arch/arm/boot/zImage \
	-dtb  linux-5.8.12/arch/arm/boot/dts/vexpress-v2p-ca9.dtb \
	-append "root=/dev/mmcblk0 rw console=tty0" \
	-sd rootfs.ext3

QEMU网络功能设置

  1. 配置QEMU与主机的网络连接
  • 采用桥接bridge的网络连接与Host通信;
  • 需要主机内核tun/tap模块支持;
  1. 配置命令
// 添加依赖
sudo apt install uml-utilities bridge-utils

// 创建tun设备文件/dev/net/tun
// 查看当前系统下是否存在tun结点,一般系统都有
ls /dev/net/

// 查看当前主机的ip
sudo apt install net-tools
ifconfig
// 修改/etc/network/interfaces文件,重启生效
sudo gedit /etc/network/interfaces

%% 修改内容为(此行不复制)

# interfaces(5) file used by ifup(8) and ifdown(8)
auto lo
iface lo inet loopback

auto enp0s5 // 自己对应的网口名

auto br0 // 创建网口
iface br0 inet dhcp
bridge_ports enp0s5

%% end(此行不复制)
// 配置/etc/qemu-ifup   和 /etc/qemu-ifdown 
// 系统都存在着两文件就不需要进行配置
ls /etc/qemu-if*  // 查看文件是否存在

sudo reboot //重启 
  • 修改前ifconfig
    在这里插入图片描述

  • 修改后ifconfig
    在这里插入图片描述

使用u-boot加载内核

  1. 介绍
  • 嵌入式bootloader
    功能类似于pc 的BIOS,硬件检测是否正常;
    加载操作系统镜像到RAM;
    设置不同的启动方式
  • 常见的启动方式
    NOR/NAND flash启动
    SD卡启动
    Bootloader从网络加载Linux内核启动
U-boot编译
  1. 类似Windows的BIOS;
  2. 下载U-boot
  3. 修改Makefile
tar -xvf u-boot-2020.10-rc5.tar.bz2
cd u-boot-2020.10-rc5
gedit Makefiel

%% 以下内容在Makefile文件内修改
// 在原有的CROSS_COMPILE	?= 下面添加下句
CROSS_COMPILE	?= arm-linux-gnueabi-

在这里插入图片描述

gedit config.mk

%% 以下内容在config.mk文件内修改
ARCH := $(CONFIG_SYS_ARCH:"%"=%)
改为
ARCH := arm
  1. 配置u-boot的启动方式tftp 或 nfs -自动化引导
// 当前目录u-boot-2020.10-rc5/

vim include/configs/vexpress_common.h
  • 支持tftp启动
    uImage 加载到0x60003000
    vexpress-v2p-ca9.dtb 加载到0x60050000
    bootargs 采用sd卡挂载系统
    系统启动跳到0x60003000
    CONFIG_IPADDR 开发板的ip地址,自己定义
    CONFIG_SERVERIP 主机的ip/虚拟机的ip地址
/* Basic environment settings */
/*#define CONFIG_BOOTCOMMAND \
        "run distro_bootcmd; " \
        "run bootflash; "*/
#define CONFIG_BOOTCOMMAND \
        "tftp 0x60003000 uImage;tftp 0x60500000 vexpress-v2p-ca9.dtb;\
        setenv bootargs 'root=/dev/mmcblk0 console=ttyAMA0';\
        bootm 0x60003000 - 0x60500000;"
#define CONFIG_IPADDR 10.211.55.18
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_SERVERIP 10.211.55.17
  • 支持nfs启动(略过) 注nfsroot中rootfs路径对应修改
/* Basic environment settings */
/*#define CONFIG_BOOTCOMMAND \
        "run distro_bootcmd; " \
        "run bootflash; "*/
#define CONFIG_BOOTCOMMAND \
        "tftp 0x60003000 uImage;tftp 0x60500000 vexpress-v2p-ca9.dtb;\
        setenv bootargs 'root=/dev/nfs rw \
        nfsroot=10.211.55.18:/Desktop/YourHost/Desktop/rootfs init=/linuxrc \
        ip=10.211.55.18  console=ttyAMA0';\
        bootm 0x60003000 - 0x60500000;"
#define CONFIG_IPADDR 10.211.55.18
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_SERVERIP 10.211.55.17
  • 不进行tftp启动 或 nfs启动设置,在测试u-boot时可能会出现镜像找不到错误

在这里插入图片描述

在这里插入图片描述

  1. 配置与编译
// 当前目录u-boot-2020.10-rc5/

make vexpress_ca9x4_defconfig
make -j4

// 编译后会在当前目录下生成多个u-boot-xxx文件
  1. 测试 & 运行 u-boot
// 当前目录u-boot-2020.10-rc5/

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

内核配置编译

  1. 使用u-boot引导内核镜像
  • 需要将内核编译为uImage格式;
  • 需要指定uImage的加载地址;
  • 编译时指定: make LOADADDR= xxx uImage -j4
  1. 编译命令
// 进入linux内核目录位置
cd linux-5.8.12

// 虚拟开发板的内存地址从0x60000000开始
make LOADADDR=0x60003000 uImage -j4
// 查看arch/arm/boot/目录下,生成了一个uImage文件
ls arch/arm/boot/

主机TFTP工具安装

  1. 安装配置命令
// 安装tftp工具
sudo apt install tftp-hpa tftpd-hpa xinetd

// 修改配置文件
sudo vim /etc/default/tftpd-hpa

// 创建tftp目录
// tftpboot目录的作用:
	// 虚拟开发板通过tftpboot目录从主机下载uImage 镜像文件;
	// 需要将uImage内核镜像放入tftpboot目录下

mkdir /home/tftpboot
sudo chmod 777 tftpboot

// 重启tftp服务
sudo /etc/init.d/tftpd-hpa restart
  1. 制作脚本boot_uboot.sh
touch boot_uboot.sh
sudo chmod 755 boot_uboot.sh
gedit boot_uboot.sh

%% boot_uboot.sh添加下述内容

qemu-system-arm \
	-M vexpress-a9 \
	-kernel u-boot \
	-nographic \
	-m 512M \
	-net nic,vlan=0 -net tap,vlan=0,ifname=tap0 \
	-sd ~/Desktop/rootfs.ext3

%% end
  1. 将uImage相关文件复制到tftpboot目录中
// 拷贝文件有u-boot boot_uboot.sh vexpress-v2p-ca9.dtb uImage

// uImage
cp linux-5.8.12/arch/arm/boot/uImage /home/tftpboot/

// vexpress-v2p-ca9.dtb
cp linux-5.8.12/arch/arm/boot/dts/vexpress-v2p-ca9.dtb /home/tftpboot/

// u-boot
cp u-boot-2020.10-rc5/u-boot /home/tftpboot/

// boot_uboot.sh
cp ~/Desktop/boot_uboot.sh /home/tftpboot/
  1. 测试 u-boot引导uImage
cd /home/tftpboot/
sudo ./boot_uboot.sh

挂载NFS文件系统

  1. NFS文件系统是一种共享文件系统,针对上述出现每次修改内核文件系统时需要挂载一个SD卡,操作麻烦的问题。

  2. ubuntu(主机)需要支持NFS服务

// 主机上安装NFS服务
sudo apt install nfs-kernel-server
  1. 修改/etc/exports文件 — 路径对应修改
  • rw: 读写
  • sync: 同步
  • no_root_squash: 登入 NFS 主机使用分享目录的使用者,如果是 root 的话,那么对于这个分享的目录来说,他就具有 root 的权限
  • no_sbutree_check: 不检验根文件系统的子目录
sudo gedit /etc/exports

// 在/etc/exports文件中末尾添加:

/home/rootfs *(rw,sync,no_root_squash,no_subtree_check)

// /home/rootfs目录时busybox制作的,让rootfs为根文件系统, 共享文件目录
// 我将rootfs目录存放在桌面故我添加的是 ---- 绝对路径 不能写~/Desktop/rootfs
/home/UserName/Desktop/rootfs *(rw,sync,no_root_squash,no_subtree_check)
  • 重启服务
/etc/init.d/rpcbind restart
/etc/init.d/nfs-kernel-server restart
  1. 修改/include/configs/vexpress_common.h文件
  • 路径u-boot-2020.10-rc5/include/configs/vexpress_common.h
// 当前目录u-boot-2020.10-rc5/
gedit include/configs/vexpress_common.h


// bootargs启动参数
1. root=/dev/mmcblk0 -> root=/dev/nfs
2. nfsroot=10.211.55.18 主机ip地址
3. /home/YourHost/Desktop/rootfs rootfs文件的路径
4. ip=10.211.55.18 虚拟主板的虚拟ip地址

%% 修改内容(此行不复制)

/* Basic environment settings */
/*#define CONFIG_BOOTCOMMAND \
        "run distro_bootcmd; " \
        "run bootflash; "*/
#define CONFIG_BOOTCOMMAND \
        "tftp 0x60003000 uImage;tftp 0x60500000 vexpress-v2p-ca9.dtb;\
        setenv bootargs 'root=/dev/nfs rw \
        nfsroot=10.211.55.17:/home/YourHost/Desktop/rootfs init=/linuxrc \
        ip=10.211.55.18  console=ttyAMA0';\
        bootm 0x60003000 - 0x60500000;"
#define CONFIG_IPADDR 10.211.55.18
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_SERVERIP 10.211.55.17

%% end(此行不复制)
// 编译
make

// 拷贝
cp u-boot /home/tftpboot/
  1. 内核支持挂载NFS文件系统
  • 修改BOOTCOMMAND
// 当前目录linux-5.8.12/
make menuconfig

// File System -> Network File System 如图选择4个 

// 关于Root file system on NFS选项不存在问题
// 打开第一级菜单下的Networking support -> Networking options -> TCP/IP networking -> IP: kernel level autoconfiguration。
// 如果NFS要使用DHCP,还得选上 IP: DHCP support

在这里插入图片描述

// 重新编译

make LOADADDR=0x60003000 uImage -j4

// 拷贝
cp arch/arm/boot/uImage /home/tftpboot/
  • 运行测试
// 当前目录/home/tftproot
sudo ./boot_uboot.sh
  • 如果主机是Ubuntu18.04系统可能会出现问题 挂载失败

  • 效果 - 方便开发,避免每次主机和开发板传输文件需要挂载SD卡
    在主机rootfs文件内添加Hello.txt
    在这里插入图片描述
    虚拟开发板也对应产生Hello.txt文件
    在这里插入图片描述

完善NFS根文件系统

增加内核的各种用户接口和重启reboot功能
0. 介绍

  • 启动顺序
    linux 内核启动之后, 挂载NFS根文件系统;
    init进程boottargs ----> inittab
    执行init.d/rcS 挂载各种文件目录(跟fstab有关)
    执行console前执行profile
  1. 在根文件系统下etc目录下添加inittab, profile, fstab
  • fstab 内容
proc		/proc		proc	defaults    		0	0
tmpfs           /tmp            tmpfs   defaults                0       0
sysfs           /sys            sysfs   defaults                0       0
tmpfs           /dev            tmpfs   defaults                0       0
var             /dev            tmpfs   defaults                0       0
ramfs           /dev            ramfs   defaults                0       0
  • profile 内容
PS1='perfect@vexpress:\w # ' 
export PS1 
  • initial 内容
::sysinit:/etc/init.d/rcS
#::respawn:-/bin/sh
#tty2::askfirst:-/bin/sh
#::ctrlaltdel:/bin/umount -a -r

console::askfirst:-/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
  1. 新建tmp, sys, var, proc目录
// 在rootfs目录内添加,NFS会同步到虚拟主板上
mkdir tmp sys var proc
就此结束了

补充

  • 了解uImage和zImage:
    linux内核经过编译后会生成一个elf格式的可执行程序,叫做vmlinux或vmlinuz,这个是原始的未经任何处理加工的原版内核elf文件,嵌入式系统部署时烧录一般不是这个vmlinux,而是要用objcopy工具去制作成烧录镜像格式的文件Image(这个制作烧录镜像主要目的是缩减大小,节省磁盘)。原则上Image就可以直接被烧录在flash上启动执行,,但是实际并不是那么简单,实际上linux的作者们觉得Image还是太大了,所以对Image
    进行了也压缩,并且在Image压缩后的文件的前端附加了一部分解压缩代码,构成了一个压缩格式的镜像叫做zImage,解压的时候,通过zImage镜像头部的解压缩代码进行自解压,然后执行自解压出来的内核镜像。
    同时,uboot为了启动linux内核,还发明了一种内核格式叫做uImage,uImage是由zImage加工得到的,uboot中有一个工具,可以将zImage加工成uImage,uImage是不管linux内核的事情,linux内核只管生成zImage,然后uboot中的mkimage工具再去由zImage加工成uImage来给uboot启动,这个加工过程时间就是在zImage前边加上64字节的uImage的头信息即可。
    注:如果直接在kernel底下去make uImage会提示mkimage command not found,解决方式是去uboot/tools目录下执行cp mkimage /usr/local/bin 复制mkimage工具到系统目录下,再去make uImage即可。
    原则上,uboot启动时应该给他uImage格式的镜像,但是实际上uboot中也支持zImage,是否支持就看是否定义了LINUX_ZIMAGE_MAGIC这个宏,所以可以看出,有些uboot是支持zImage启动的,有些是不支持的,但是所有的uboot肯定都支持uImage启动。

参考文章
参考文章

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值