说明:
QEMU,它是一个开源的可执行硬件虚拟化的托管虚拟机,可以虚拟出甚至cortex A的开发板,提供必备的外设:串口等等,几乎可以实现在线学习arm开发,因此,在没有开发板的情况下,也可以玩转ARM。
开始前,那就得有环境呀,so,开始吧。
环境准备:
Oracle VM VirtualBox
Ubuntu20.04
材料准备:
安装 vim
sudo apt-get install vim
git安装:
apt install git
make安装:
sudo apt install make
sudo apt-get install libncurses5-dev libncursesw5-dev //支持make menuconfig图形化配置
安装ARM-Linux-GCC工具链
sudo apt-get install gcc-arm-linux-gnueabi
安装uboot工具
sudo apt install u-boot-tools
安装qume模拟器:
sudo apt install qemu-system-arm
查看版本:
# qemu-system-arm --version
QEMU emulator version 4.2.1 (Debian 1:4.2-3ubuntu6.18)
Copyright (c) 2003-2019 Fabrice Bellard and the QEMU Project developers
git下载linux内核源码
pwd>
/home/qemu-linux-kits
git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
官网下载经常速度太慢,无法下载,提供另一个链接:
http://ftp.sjtu.edu.cn/sites/ftp.kernel.org/pub/linux/kernel/
git下载u-boot源码:
pwd
/home/qemu-linux-kits
git clone git://git.denx.de/u-boot.git u-boot
busybox网站:
git下载busybox源码:
pwd
/home/qemu-linux-kits
git clone git://busybox.net/busybox.git
切换到稳定版本:
git checkout remotes/origin/1_NN_stable
更新源码到最新:
git pull
注:后两步没成功
准备工作完成。
开始工作:
解压linux内核
tar -zxvf linux-4.17.tar.gz
cd linux-4.17
修改Makefile文件:大概324行
ARCH?= $(SUBARCH)
CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)
修改为:
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-gnueabi-
注:
vim中查找字符串,命令状态下:/要查找字符+回车+n
配置对应的开发板
这里用的是vexpress-a9,如下:
make vexpress_defconfig
报了个错:
make: *** arch/arm: Is a directory. Stop.
原因:
修改时Makefile中ARCH=arm这一句后面多了两个空格,删除即可。
不修改Makefile文件,可以外面指定如下:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
编译zImage,module以及dtb:
make zImage
CC arch/arm/boot/compressed/misc.o
CC arch/arm/boot/compressed/decompress.o
CC arch/arm/boot/compressed/string.o
AS arch/arm/boot/compressed/hyp-stub.o
AS arch/arm/boot/compressed/lib1funcs.o
AS arch/arm/boot/compressed/ashldi3.o
AS arch/arm/boot/compressed/bswapsdi2.o
LD arch/arm/boot/compressed/vmlinux
OBJCOPY arch/arm/boot/zImage
Kernel: arch/arm/boot/zImage is ready
zImage生成路径:
arch/arm/boot/zImage
make modules
LD [M] crypto/hmac.ko
CC crypto/jitterentropy_rng.mod.o
LD [M] crypto/jitterentropy_rng.ko
CC crypto/sha256_generic.mod.o
LD [M] crypto/sha256_generic.ko
CC drivers/video/backlight/lcd.mod.o
LD [M] drivers/video/backlight/lcd.ko
modules生成路径:
drivers/video/backlight/*.ko
make dtbs
CHK include/config/kernel.release
CHK include/generated/uapi/linux/version.h
CHK include/generated/utsrelease.h
CHK include/generated/bounds.h
CHK include/generated/timeconst.h
CHK include/generated/asm-offsets.h
CALLscripts/checksyscalls.sh
CHK scripts/mod/devicetable-offsets.h
DTC arch/arm/boot/dts/vexpress-v2p-ca5s.dtb
DTC arch/arm/boot/dts/vexpress-v2p-ca9.dtb
DTC arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dtb
DTC arch/arm/boot/dts/vexpress-v2p-ca15_a7.dtb
dtbs生成路径:
arch/arm/boot/dts/vexpress-v2p-ca9.dtb
busybox制作根文件系统
cd busybox/
修改Makefile,新的busybox的makefile下面的选项是空配置的,需要修改如下:
CROSS_COMPILE ?= arm-linux-gnueabi-
ARCH ?= arm
配置
make defconfig或者make menuconfig
生成.config文件
/busybox# ls -al .config
-rw-r--r-- 1 root root 29073 12月 4 13:45 .config
编译 && 安装
make
输出结果:
…
LINKbusybox_unstripped
Trying libraries: m resolv rt
DOC busybox.1
DOC BusyBox.html
make install
输出结果:
..
./_install//usr/sbin/udhcpd -> ../../bin/busybox
--------------------------------------------------
You will probably need to make your busybox binary
setuid root to ensure all configured applets will
work properly.
--------------------------------------------------
生成的的_install文件如下,包含了各种shell命令
/busybox# ls -al ./_install/
total 20
drwxr-xr-x 5 root root 4096 12月 4 13:56 .
drwxr-xr-x 38 root root 4096 12月 4 13:56 ..
drwxr-xr-x 2 root root 4096 12月 4 13:56 bin
lrwxrwxrwx 1 root root 11 12月 4 13:56 linuxrc -> bin/busybox
drwxr-xr-x 2 root root 4096 12月 4 13:56 sbin
drwxr-xr-x 4 root root 4096 12月 4 13:56 usr
制作根文件系统
pwd
/home/qemu-linux-kits
新建根目录:
root@ibm:/home/qemu-linux-kits# mkdir trainning
root@ibm:/home/qemu-linux-kits# cd trainning/
root@ibm:/home/qemu-linux-kits/trainning# mkdir rootfs
root@ibm:/home/qemu-linux-kits/trainning# cd rootfs/
root@ibm:/home/qemu-linux-kits/trainning/rootfs# mkdir lib
root@ibm:/home/qemu-linux-kits/trainning/rootfs# ls
lib
拷贝库文件:
root@ibm:/home/qemu-linux-kits/trainning/rootfs# cp -r ../../busybox/_install/* ./
root@ibm:/home/qemu-linux-kits/trainning/rootfs# ls
bin lib linuxrc sbin usr
文件系统运行在arm平台,因此还需要arm-linux-gnueabi的库
root@ibm:/home/qemu-linux-kits/trainning/rootfs# cp -p /usr/arm-linux-gnueabi/lib/* ./lib
root@ibm:/home/qemu-linux-kits/trainning/rootfs# ls ./lib/
crt1.o libgomp.so.1libnss_nis.so.2
...
libgcc_s.so.1libnss_nis.so Scrt1.o
创建设备文件
/home/qemu-linux-kits/trainning/rootfs
mkdir dev
root@ibm:/home/qemu-linux-kits/trainning/rootfs# ls
bin dev lib linuxrc sbin usr
创建4个串口设备
pwd
/home/qemu-linux-kits/trainning/rootfs/dev
root@ibm:/home/qemu-linux-kits/trainning/rootfs/dev# sudo mknod -m 666 tty1 c 4 1
root@ibm:/home/qemu-linux-kits/trainning/rootfs/dev# sudo mknod -m 666 tty2 c 4 2
root@ibm:/home/qemu-linux-kits/trainning/rootfs/dev# sudo mknod -m 666 tty3 c 4 3
root@ibm:/home/qemu-linux-kits/trainning/rootfs/dev# sudo mknod -m 666 tty4 c 4 4
创建控制台
sudo mknod -m 666 console c 5 1
创建null
sudo mknod -m 666 null c 1 3
pwd
/home/qemu-linux-kits/trainning/rootfs/dev
ls
console null tty1 tty2 tty3 tty4
制作SD根文件系统镜像
pwd
/home/qemu-linux-kits/trainning
root@ibm:/home/qemu-linux-kits/trainning# dd if=/dev/zero of=rootfs.ext3 bs=1M count=64
32+0 records in
32+0 records out
33554432 bytes (34 MB, 32 MiB) copied, 0.214002 s, 157 MB/s
root@ibm:/home/qemu-linux-kits/trainning# mkfs.ext3 rootfs.ext3
mke2fs 1.45.5 (07-Jan-2020)
Discarding device blocks: done
Creating filesystem with 8192 4k blocks and 8192 inodes
Allocating group tables: done
Writing inode tables: done
Creating journal (1024 blocks): done
Writing superblocks and filesystem accounting information: done
将虚拟sd卡挂载到/mnt,拷贝rootfs的所有文件到sd,卸载sd(块设备不能直接读写)
pwd
/home/qemu-linux-kits/trainning
mount -t ext3 rootfs.ext3 /mnt/ -o loop
cp -r rootfs/* /mnt
ls /mnt/
bin dev lib linuxrc lost+found sbin usr
umount /mnt
启动内核,挂载rootfs
pwd
/home/qemu-linux-kits/trainning
无LCD启动:
qemu-system-arm -M vexpress-a9 -m 512M -dtb ../linux-4.17/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -kernel ../linux-4.17/arch/arm/boot/zImage -nographic -append "root=/dev/mmcblk0 rw console=ttyAMA0" -sd rootfs.ext3
打印结果如下:
Booting Linux on physical CPU 0x0
Linux version 4.17.0 (root@ibm) (gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04)) #1 SMP Sat Dec 4 08:50:17 CST 2021
CPU: ARMv7 Processor [410fc090] revision 0 (ARMv7), cr=10c5387d
CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
OF: fdt: Machine model: V2P-CA9
Memory policy: Data cache writeback
CPU: All CPU(s) started in SVC mode.
random: get_random_bytes called from start_kernel+0x9c/0x478 with crng_init=0
percpu: Embedded 16 pages/cpu @(ptrval) s36364 r8192 d20980 u65536
Built 1 zonelists, mobility grouping on. Total pages: 130048
Kernel command line: root=/dev/mmcblk0 rw console=ttyAMA0
...
EXT4-fs (mmcblk0): mounting ext3 file system using the ext4 subsystem
random: fast init done
EXT4-fs (mmcblk0): mounted filesystem with ordered data mode. Opts: (null)
VFS: Mounted root (ext3 filesystem) on device 179:0.
Freeing unused kernel memory: 1024K
random: crng init done
***can't run '/etc/init.d/rcS': No such file or directory***
Please press Enter to activate this console.
/ # ls
bin lib lost+found usr
dev linuxrc sbin
/ #
注意上面的错误提示
有LCD启动:
qemu-system-arm -M vexpress-a9 -m 512M -dtb ../linux-4.17/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -kernel ../linux-4.17/arch/arm/boot/zImage -append “root=/dev/mmcblk0 rw console=tty0” -sd rootfs.ext3
写测试程序:
新建目录:
mkdir ko_prj
进入目录后建立两个文件:分别是hello.c和Makefile
// hello.c:
#include <linux/init.h>
#include <linux/module.h>
static int __init hello_init (void)
{
printk (KERN_INFO"[Info]Hello! enter.");
return 0;
}
module_init (hello_init);
static void __exit hello_exit (void)
{
printk (KERN_INFO"[Info]Hello! Exit .");
}
module_exit (hello_exit);
MODULE_AUTHOR ("IBM");
MODULE_LICENSE ("GPL v2");
MODULE_DESCRIPTION ("A simple test module");
MODULE_ALIAS ("hello module");
makefile文件:
#Makefile
KVERS = $(shell uname -r)
# Kernel modules
obj-m += hello.o
#EXTRA_CFLAGS=-g -O0
build: kernel_modules
kernel_modules:
make -C /lib/modules/$(KVERS)/build M=$(CURDIR) modules
clean:
make -C /lib/modules/$(KVERS)/build M=$(CURDIR) clean
编译
make
错误如下:
Makefile:12: *** missing separator (did you mean TAB instead of 8 spaces?). Stop.
这个错误是tab键缩进时导致的,特别是直接复制过来时要注意。
修改后继续:
root@ibm:/home/qemu-linux-kits/ko_prj# make
make -C /lib/modules/5.8.0-53-generic/build M=/home/qemu-linux-kits/ko_prj modules
make[1]: Entering directory '/usr/src/linux-headers-5.8.0-53-generic'
CC [M] /home/qemu-linux-kits/ko_prj/hello.o
MODPOST /home/qemu-linux-kits/ko_prj/Module.symvers
CC [M] /home/qemu-linux-kits/ko_prj/hello.mod.o
LD [M] /home/qemu-linux-kits/ko_prj/hello.ko
make[1]: Leaving directory '/usr/src/linux-headers-5.8.0-53-generic'
ls
hello.c hello.modhello.mod.o Makefile Module.symvers
hello.ko hello.mod.c hello.o modules.order
查看ko文件类型:
readelf -h hello.ko
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI:UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 3200 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 64 (bytes)
Number of section headers: 22
Section header string table index: 21
不行啊,不能在ARM板上运行啊
重新编译:
修改Makefile文件,交叉工具链编译即可如下:
#Makefile
#KVERS = $(shell uname -r)
KDIR=/home/qemu-linux-kits/linux-4.17
PWD=$(shell pwd)
# Kernel modules
obj-m += hello.o
module-objs = hello.o
ARCH=arm
CROSS_COMPILE=arm-linux-gnueabi-
CC := $(CROSS_COMPILE)gcc
LD := $(CROSS_COMPILE)ld
#EXTRA_CFLAGS=-g -O0
default:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -f *.ko *.o *.mod.c *.symvers *.order
再编译一次:
make
查看类型:
readelf -h hello.ko
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI:UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: ARM
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 60916 (bytes into file)
Flags: 0x5000000, Version5 EABI
Size of this header: 52 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 40 (bytes)
Number of section headers: 37
Section header string table index: 36
测试KO文件:
注:QEMU启动后,再退出QEMU的快捷键:ctrl+a x
开始测试先在
rootfs根文件系统下面创建一个test目录用来存放ko文件
mkdir test_ko
pwd
/home/qemu-linux-kits/trainning/rootfs/test_ko
cp /home/qemu-linux-kits/ko_prj/hello.ko ./
ls
hello.ko
拷贝rootfs的内容到rootfs.ext3虚拟SD中
pwd
/home/qemu-linux-kits/trainning
mount -t ext3 rootfs.ext3 /mnt/ -o loop
cp -r rootfs/* /mnt
umount /mnt
启动开发板
pwd
/home/qemu-linux-kits/trainning
无LCD启动:
qemu-system-arm -M vexpress-a9 -m 512M -dtb ../linux-4.17/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -kernel ../linux-4.17/arch/arm/boot/zImage -nographic -append “root=/dev/mmcblk0 rw console=ttyAMA0” -sd rootfs.ext3
打印信息省略…
注:
can’t run ‘/etc/init.d/rcS’: No such file or directory
说明文件系统还没OK呀
Please press Enter to activate this console.
/ # ls
bin lib lost+found test_ko
dev linuxrc sbinusr
/ # cd test_ko/
/test_ko # insmod ./hello.ko
hello: loading out-of-tree module taints kernel.
内核树不一样导致上面的问题。
开发板:
uname -r
4.17.0
主机:
uname -r
5.8.0-53-generic
对后续的内核insmod并无影响,可以不用管。最好解决方法,可以找两个内核版本一样的。
test_ko # rmmod hello.ko
[Info]Hello! enter.
/test_ko # insmod hello.ko
[Info]Hello! Exit .
/test_ko # rmmod hello.ko
[Info]Hello! enter.
现在开始修复:
can’t run ‘/etc/init.d/rcS’: No such file or directory
进一步完善根文件系统
创建etc
mkdir etc
root@ibm:/home/qemu-linux-kits/trainning/rootfs# cd etc/
root@ibm:/home/qemu-linux-kits/trainning/rootfs/etc# pwd
/home/qemu-linux-kits/trainning/rootfs/etc
创建inittab
::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
创建fstab
proc/proc procdefaults0 0
tmpfs /tmptmpfs defaults0 0
sysfs /syssysfs defaults0 0
tmpfs /devtmpfs defaults0 0
var /devtmpfs defaults0 0
ramfs /devramfs defaults0 0
创建profile
PS1='ibm@arm-vexpress:\w # '
export PS1
创建init.d/rcS
#! /bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
LD_LIBRARY_PATH=/lib
export PATH LD_LIBRARY_PATH
mount -a
mkdir -p /dev/pts
mount -t devpts devpts /dev/pts
mdev -s
mkdir -p /var/lock
echo "-----------------------------------"
echo " welcome to A9 vexpress board"
echo "-----------------------------------"
用最新的rootfs覆盖rootfs.ext3虚拟SD卡,启动开发板验证
pwd
/home/qemu-linux-kits/trainning
mount -t ext3 rootfs.ext3 /mnt/ -o loop
cp -r rootfs/* /mnt
umount /mnt
启动开发板
pwd
/home/qemu-linux-kits/trainning
无LCD启动:
qemu-system-arm -M vexpress-a9 -m 512M -dtb ../linux-4.17/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -kernel ../linux-4.17/arch/arm/boot/zImage -nographic -append “root=/dev/mmcblk0 rw console=ttyAMA0” -sd rootfs.ext3
提示一个错误:
can’t run ‘/etc/init.d/rcS’: Permission denied
修改上述文件的权限:
chmod 777 xxx 或 chmod +rwx xxx
重启开发板,新错误:
random: crng init done
mount: mounting proc on /proc failed: No such file or directory
mount: mounting tmpfs on /tmp failed: No such file or directory
mount: mounting sysfs on /sys failed: No such file or directory
mdev: /sys/dev: No such file or directory
-----------------------------------
welcome to A9 vexpress board
-----------------------------------
can't open /dev/console: No such file or directory
can't open /dev/console: No such file or directory
can't open /dev/console: No such file or directory
QEMU: Terminated
是参考的文档写的不全造成的 如:根文件系统都没有/proc目录
创建几个目录再:
pwd
/home/qemu-linux-kits/trainning/rootfs
mkdir proc
mkdir tmp
mkdir sys
再用最新的rootfs覆盖rootfs.ext3虚拟SD卡,启动开发板验证
打印信息如此:
...
VFS: Mounted root (ext3 filesystem) on device 179:0.
Freeing unused kernel memory: 1024K
random: crng init done
-----------------------------------
welcome to A9 vexpress board
-----------------------------------
Please press Enter to activate this console.
目前看一切OK啦
使用u-boot加载linux kernel
pwd
/home/qemu-linux-kits/u-boot
修改顶层Makefile,指定交叉编译器
CROSS_COMPILE ?= arm-linux-gnueabi-
修改顶层config.mk,指定ARM架构
ARCH := arm
配置开发板
make vexpress_ca9x4_defconfig
HOSTCC scripts/basic/fixdep
HOSTCC scripts/kconfig/conf.o
YACCscripts/kconfig/zconf.tab.c
LEX scripts/kconfig/zconf.lex.c
HOSTCC scripts/kconfig/zconf.tab.o
HOSTLD scripts/kconfig/conf
#
# configuration written to .config
#
编译u-boot
make –j4
错误:
cc1: error: bad value (‘generic-armv7-a’) for ‘-mtune=’ switch
错误原因:
编译时未明确设置默认交叉编译工具
解决办法:
在Uboot顶层目录下继续修改Makefile
# set default to nothing for native builds
ifeq ($(HOSTARCH),$(ARCH))
CROSS_COMPILE ?=arm-linux-gnueabi-
endif
ARCH = arm
CROSS_COMPILE ?=arm-linux-gnueabi- #增加了两行(本行+上1行)
KCONFIG_CONFIG ?= .config
export KCONFIG_CONFIG
编译结果:
AR lib/built-in.o
LD u-boot
OBJCOPY u-boot.srec
OBJCOPY u-boot-nodtb.bin
SYM u-boot.sym
COPYu-boot.bin
运行u-boot
pwd
/home/qemu-linux-kits/u-boot
qemu-system-arm -M vexpress-a9 -kernel u-boot -nographic -m 512M
输出:
U-Boot 2022.01-rc3-00015-g5b9ee01685-dirty (Dec 05 2021 - 08:46:08 +0800)
DRAM: 512 MiB
WARNING: Caches not enabled
Flash: 64 MiB
MMC: mmci@5000: 0
Loading Environment from Flash... *** Warning - bad CRC, using default environment
In:serial
Out: serial
Err: serial
Net: eth0: ethernet@3,02000000
...
Usage:
cp [.b, .w, .l, .q] source target count
Wrong Image Format for bootm command
ERROR: can't get kernel image!
=> QEMU: Terminated
退出QEMU快捷键:ctrl+a x
看到上面打印信息,说明 U-boot启动正常,但要用u-boot引导内核启动,先要搞定网络…
配置QEMU的网络功能
采用桥接(bridge)的网络连接与Host通信,需要主机内核tun/tap模块支持(linux17.04以后的版本都支持了,不支持的老版本需要自己创建,我安装的ubuntu是20.04,故已经有了这个模块)
root@ibm:/home/qemu-linux-kits/u-boot# ls /dev/net/
tun
主机安装工具包:
UML(User-mode linux)工具
虚拟网桥工具
apt install uml-utilities bridge-utils
查看一下当前状况:
ifconfig
enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.35.20 netmask 255.255.255.0 broadcast 192.168.35.255
inet6 fe80::a00:27ff:fe1d:36fb prefixlen 64 scopeid 0x20<link>
ether 08:00:27:1d:36:fb txqueuelen 1000 (Ethernet)
RX packets 2830352 bytes 2300177102 (2.3 GB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1702820 bytes 311586256 (311.5 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 66060 bytes 10916745 (10.9 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 66060 bytes 10916745 (10.9 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
配网桥:
参考:
https://www.codenong.com/cs109845929/
root@ibm:/# ifconfig enp0s3 down # 首先关闭宿主机网卡接口
root@ibm:/# brctl addbr br0 # 添加一座名为 br0 的网桥
root@ibm:/# brctl addif br0 enp0s3 # 在 br0 中添加一个接口
root@ibm:/# brctl stp br0 off # 如果只有一个网桥,则关闭生成树协议
root@ibm:/# brctl setfd br0 1 # 设置 br0 的转发延迟
root@ibm:/# brctl sethello br0 1 # 设置 br0 的 hello 时间
root@ibm:/# ifconfig br0 0.0.0.0 promisc up # 启用 br0 接口
root@ibm:/# ifconfig enp0s3 0.0.0.0 promisc up # 启用网卡接口
root@ibm:/# dhclient br0 # 从 dhcp 服务器获得 br0 的 IP 地址
root@ibm:/# brctl show br0 # 查看虚拟网桥列表
bridge name bridge id STP enabled interfaces
br0 8000.0800271d36fb no enp0s3
root@ibm:/# brctl showstp br0 # 查看 br0 的各接口信息
br0
bridge id 8000.0800271d36fb
designated root 8000.0800271d36fb
root port 0 path cost 0
max age 20.00 bridge max age 20.00
hello time 1.00 bridge hello time 1.00
forward delay 1.00 bridge forward delay 1.00
ageing time 300.00
hello timer 0.00 tcn timer 0.00
topology change timer 0.00 gc timer 225.02
flags
enp0s3 (1)
port id 8001 state forwarding
designated root 8000.0800271d36fb path cost 4
designated bridge 8000.0800271d36fb message age timer 0.00
designated port 8001 forward delay timer 0.00
designated cost 0 hold timer 0.00
flags
查看一下当前的状态:
root@ibm:/# ifconfig
br0: flags=4419<UP,BROADCAST,RUNNING,PROMISC,MULTICAST> mtu 1500
inet 192.168.35.11 netmask 255.255.255.0 broadcast 192.168.35.255
inet6 fe80::a00:27ff:fe1d:36fb prefixlen 64 scopeid 0x20<link>
ether 08:00:27:1d:36:fb txqueuelen 1000 (Ethernet)
RX packets 35 bytes 6690 (6.6 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 54 bytes 6707 (6.7 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
enp0s3: flags=4419<UP,BROADCAST,RUNNING,PROMISC,MULTICAST> mtu 1500
ether 08:00:27:1d:36:fb txqueuelen 1000 (Ethernet)
RX packets 885 bytes 103446 (103.4 KB)
RX errors 0 dropped 1 overruns 0 frame 0
TX packets 1078 bytes 99097 (99.0 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 297 bytes 24639 (24.6 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 297 bytes 24639 (24.6 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
此时网桥已经得到了 IP,并且能够连接网络的网卡 enp0s3 也加入了网桥.
接着创建一个 TAP 设备,作为 QEMU 一端的接口:
root@ibm:/# tunctl -t tap0 -u root # 创建一个 tap0 接口,只允许 root 用户访问
Set 'tap0' persistent and owned by uid 0
root@ibm:/# brctl addif br0 tap0 # 在虚拟网桥中增加一个 tap0 接口
root@ibm:/# ifconfig tap0 0.0.0.0 promisc up # 启用 tap0 接口
root@ibm:/# brctl showstp br0 # 显示 br0 的各个接口
结果:
br0
bridge id 8000.0800271d36fb
designated root 8000.0800271d36fb
root port 0 path cost 0
max age 20.00 bridge max age 20.00
hello time 1.00 bridge hello time 1.00
forward delay 1.00 bridge forward delay 1.00
ageing time 300.00
hello timer 0.00 tcn timer 0.00
topology change timer 0.00 gc timer 84.97
flags
enp0s3 (1)
port id 8001 state forwarding
designated root 8000.0800271d36fb path cost 4
designated bridge 8000.0800271d36fb message age timer 0.00
designated port 8001 forward delay timer 0.00
designated cost 0 hold timer 0.00
flags
tap0 (2)
port id 8002 state disabled
designated root 8000.0800271d36fb path cost 100
designated bridge 8000.0800271d36fb message age timer 0.00
designated port 8002 forward delay timer 0.00
designated cost 0 hold timer 0.00
flags
网桥配置就完成。
编译uImage
pwd
/home/qemu-linux-kits/linux-4.17
make LOADADDR=0x60003000 uImage -j4
结果:
CHK include/config/kernel.release
CHK include/generated/uapi/linux/version.h
CHK include/generated/utsrelease.h
CHK scripts/mod/devicetable-offsets.h
CHK include/generated/bounds.h
CHK include/generated/timeconst.h
CHK include/generated/asm-offsets.h
CALLscripts/checksyscalls.sh
CHK include/generated/compile.h
CHK kernel/config_data.h
Kernel: arch/arm/boot/Image is ready
Kernel: arch/arm/boot/zImage is ready
UIMAGE arch/arm/boot/uImage
Image Name: Linux-4.17.0
Created: Sun Dec 5 11:27:02 2021
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size:4071640 Bytes = 3976.21 KiB = 3.88 MiB
Load Address: 60003000
Entry Point: 60003000
Kernel: arch/arm/boot/uImage is ready
主机TFTP工具安装
apt-get install tftp-hpa tftpd-hpa xinetd
修改配置文件:/etc/default/tftpd-hpa
TFTP_USERNAME="tftp"
#TFTP_DIRECTORY="/srv/tftp"
TFTP_DIRECTORY="/home/qemu-linux-kits/trainning/tftpboot"
TFTP_ADDRESS="0.0.0.0:69"
#TFTP_OPTIONS="--secure"
TFTP_OPTIONS="-l -c -s"
创建tftpboot目录
mkdir tftpboot
chmod +rwx tftpboot
/home/qemu-linux-kits/trainning/tftpboot
将必要的文件移到tftpboot
pwd
/home/qemu-linux-kits/trainning/tftpboot
ls
u-boot uImage vexpress-v2p-ca9.dtb
重启tftp服务
/etc/init.d/tftpd-hpa restart
修改u-boot文件
路径:include/configs/vexpress_common.h
目的是让u-boot完成自动引导内核文件等
/*config qemu' network<Add by ibm >*/
#define CONFIG_BOOTCOMMAND \
"tftp 0x60003000 zImage;tftp 0x60500000 vexpress-v2p-ca9.dtb; \
setenv bootargs 'root=/dev/mmcblk0 console=tty0'; \
bootm 0x60003000 - 0x60500000;"
#define CONFIG_IPADDR 192.168.35.12
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_SERVERIP 192.168.35.11
CONFIG_BOOTCOMMAND相当于如下的手动引导:
tftp 0x60003000 uImage
tftp 0x60500000 vexpress-v2p-ca9.dtb
setenv bootargs'root=/dev/mmcblk0 console=tty0'
bootm 0x60003000 - 0x60500000
再编译u-boot
编译后,启动qemu命令行
qemu-system-arm -M vexpress-a9 -kernel u-boot -nographic -m 512M -net nic -net tap,ifname=tap0,script=no,downscript=no -sd /home/qemu-linux-kits/trainning/rootfs.ext3
打印信息:
...
Loading Device Tree to 7fb20000, end 7fb267ed ... OK
Starting kernel ...
然后就没有任何反应了,停在这里了…
再修改include/configs/vexpress_common.h
#define CONFIG_BOOTCOMMAND \
"tftp 0x60003000 uImage;tftp 0x60500000 vexpress-v2p-ca9.dtb; \
setenv bootargs 'root=/dev/mmcblk0 console=ttyAMA0'; \
bootm 0x60003000 - 0x60500000; "
注意:console=ttyAMA0’ ,原来是:tty0
再重新编译u-boot:
pwd
/home/qemu-linux-kits/u-boot
make vexpress_ca9x4_defconfig
make -j4
将必要的文件移到tftpboot
pwd
/home/qemu-linux-kits/trainning/tftpboot
ls
u-boot uImage vexpress-v2p-ca9.dtb
再次启动,启动脚本如下:
qemu-system-arm -M vexpress-a9 -kernel u-boot -nographic -m 512M -net nic -net tap,ifname=tap0,script=no,downscript=no -sd /home/qemu-linux-kits/trainning/rootfs.ext3
打印信息如:
...
Freeing unused kernel memory: 1024K
random: crng init done
-----------------------------------
welcome to A9 vexpress board
-----------------------------------
Please press Enter to activate this console.
ibm@arm-vexpress:/ # ls
bin lib procsysfs tmpfs
dev linuxrc sbintest_ko usr
etc lost+found sys tmp var
ibm@arm-vexpress:/ #
结束语:
本次实操到此结束,遇到的问题基本也都详细记录下来了,希望对看到本笔记的人能有帮助。当然,如果你使用的系统、工具等版本与本笔记不同时,也可能会遇到其他意想不到的警告或错误!真的如此咋办,保持耐心 ,借助互联网一定能解决,要相信自己!