0%

基于ubuntu20.04和qemu完成u-boot引导linux kernel笔记

说明:

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网站:

https://busybox.net/source.html

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:/ # 

结束语:

本次实操到此结束,遇到的问题基本也都详细记录下来了,希望对看到本笔记的人能有帮助。当然,如果你使用的系统、工具等版本与本笔记不同时,也可能会遇到其他意想不到的警告或错误!真的如此咋办,保持耐心 ,借助互联网一定能解决,要相信自己!