kernel——开发环境搭建

1. 基于zImage

1.1 zImage

修改kernel的Makefile

 384 CROSS_COMPILE := arm-linux-gnueabi-
 385 ARCH        := arm

编译内核,模块,dtb文件

make vexpress_defconfig; make -j10 zImage
make modules -j10; make dtbs

为什么是 vexpress_defconfig呢
因为

ls arch/arm/mach-vexpress/

完成后输出文件在 arch/arm/boot/

1.2 制作根文件系统

1.2.1 什么是文件系统?

用于管理文件,包括访问,删除,新建等的结构化系统,
而其本身是文件,被应用程序读取,以实现管理文件。

在启动 zImage 后,内核需要挂载文件系统,并执行文件系统上的 init 程序。
所以使用 busybox 提供 init 程序和其他常用程序,并将其打包成文件系统,

1.2.2 编译常用应用程序

先修改 ARCH 和 CROSS_COMPILE

 164 CROSS_COMPILE := arm-linux-gnueabi-
 165 ARCH := arm

busybox 和板子无关,所以直接 defconfig 并 make

make defconfig; make; make install

把输出文件拷贝到 rootfs 目录下,拷贝c库,创建常用驱动的设备节点,这样应用程序就可以使用tty驱动

cp -r _install/* rootfs
cp -p /usr/arm-linux-gnueabi/lib/* rootfs/lib
mkdir -p rootfs/dev
mknod -n 666 tty1 c 4 1
mknod -n 666 tty2 c 4 2
mknod -n 666 tty3 c 4 3
mknod -n 666 tty4 c 4 4
mknod -n 666 tty5 c 4 5
mknod -n 666 console c 5 1
mknod -n 666 null c 1 3

1.2.2 构建文件系统

root@ubuntu:~/wlt# dd if=/dev/zero of=rootfs.ext3 bs=1M count=32
32+0 records in
32+0 records out
33554432 bytes (34 MB, 32 MiB) copied, 0.0208796 s, 1.6 GB/s
root@ubuntu:~/wlt# mkfs.ext3 rootfs.ext3
mke2fs 1.42.13 (17-May-2015)
Discarding device blocks: done
Creating filesystem with 32768 1k blocks and 8192 inodes
Filesystem UUID: 68483364-3a40-47f8-bbaa-2f2345cac918
Superblock backups stored on blocks:
        8193, 24577

Allocating group tables: done
Writing inode tables: done
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done

# 将文件系统挂载到 /mnt 目录
root@ubuntu:~/wlt# mount -t ext3 rootfs.ext3 /mnt/ -o loop
# 将busybox的程序拷贝到文件系统
root@ubuntu:~/wlt# cp rootfs/* /mnt/ -r
# 卸载
root@ubuntu:~/wlt# umount /dev/loop0

启动

qemu-system-arm         \
        -M vexpress-a9  \
        -m 512M         \
        -kernel /root/wlt/image/zImage  \
        -dtb /root/wlt/image/vexpress-v2p-ca9.dtb \
        -nographic      \
        -append "root=/dev/mmcblk0 rw console=ttyAMA0" \
        -sd /root/wlt/rootfs.ext3

2. 基于uImage

2.1 uboot

显然基于zImage的镜像有个缺点,即 一级引导程序负责初始化硬件,并启动内核,导致一级引导程序大,
所以通常用二级引导。如uboot完成 初始化硬件,启动内核。

2.1.1 编译uboot

为了方便测试,静态修改环境变量
vi include/configs/vexpress_common.h

  187 #define CONFIG_IPADDR 192.168.5.128
  188 #define CONFIG_NETMASK 255.255.255.0
  189 #define CONFIG_SERVERIP 192.168.5.129
  190
  191 #define BOOT_NFS
  192 #undef BOOT_NFS
  193 #ifndef BOOT_NFS
  194
  195 #define CONFIG_BOOTCOMMAND \
  196     "tftp 0x60003000 uImage; tftp 0x60500000 vexpress-v2p-ca9.dtb; \
  197     setenv bootargs 'root=/dev/mmcblk0 console=ttyAMA0'; \
  198     bootm 0x60003000 - 0x60500000;"
  199
  200 #else
  201
  202 #define CONFIG_BOOTCOMMAND \
  203     "tftp 0x60003000 uImage; tftp 0x60500000 vexpress-v2p-ca9.dtb; \
  204     setenv bootargs 'root=/dev/nfs rw \
  205     nfsroot=192.168.5.129:/root/wlt/rootfs \
  206     ip=192.168.5.127 \
  207     init=/linuxrc console=ttyAMA0'; \
  208     bootm 0x60003000 - 0x60500000;"
  209
  210 #endif

uboot是板级相关的,所以要选择板子信息

make vexpress_ca9x4_defconfig
make

2.1.2 qemu和主机通网

添加虚拟网卡

modprobe tun
apt install uml-utilities

添加一个tap

tunctl -b
ip link set tap0 up

桥接

apt install bridge-utils
brctl addbr br0
brctl addif br0 ens33
ifconfig br0 192.168.5.133 netmask 255.255.255.0
brctl addif br0 tap0

如果ens33有ip则需要删除

ip -o -f inet addr show
删除ip 
ip -f inet addr delete 10.0.64.102/32  dev ens33

添加qemu参数

-net nic -net tap,ifname=tap0

2.2 构建uImage

make LOADADDR=0x60003000 uImage

2.3 启动

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

2.4 使用nfs

2.4.1 主机配置nfs server

root@ubuntu:~/wlt# cat /etc/exports
# /etc/exports: the access control list for filesystems which may be exported
#               to NFS clients.  See exports(5).
#
# Example for NFSv2 and NFSv3:
# /srv/homes       hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check)
#
# Example for NFSv4:
# /srv/nfs4        gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
# /srv/nfs4/homes  gss/krb5i(rw,sync,no_subtree_check)
#
/root/wlt/rootfs  *(rw,sync,no_subtree_check,no_root_squash)
/home/test/rootfs  *(rw,sync,no_subtree_check,no_root_squash)

2.4.2 启动nfs服务器

root@ubuntu:~/wlt# /etc/init.d/rpcbind restart
[ ok ] Restarting rpcbind (via systemctl): rpcbind.service^[[A.
root@ubuntu:~/wlt# /etc/init.d/nfs-kernel-server restart
[ ok ] Restarting nfs-kernel-server (via systemctl): nfs-kernel-server.service.

2.4.3 内核配置nfs客户端

│ │ File systems --->
│ │ [] Network File Systems --->
│ │ <
> NFS client support │ │
│ │ <> NFS client support for NFS version 2 │ │
│ │ <
> NFS client support for NFS version 3 │ │
│ │ [] NFS client support for the NFSv3 ACL protocol extension
│ │ [
] Root file system on NFS

2.4.4 设置uboot的启动参数为 nfs启动

vi include/configs/vexpress_common.h

  187 #define CONFIG_IPADDR 192.168.5.128
  188 #define CONFIG_NETMASK 255.255.255.0
  189 #define CONFIG_SERVERIP 192.168.5.129
  190
  191 #define BOOT_NFS
  193 #ifndef BOOT_NFS
  194
  195 #define CONFIG_BOOTCOMMAND \
  196     "tftp 0x60003000 uImage; tftp 0x60500000 vexpress-v2p-ca9.dtb; \
  197     setenv bootargs 'root=/dev/mmcblk0 console=ttyAMA0'; \
  198     bootm 0x60003000 - 0x60500000;"
  199
  200 #else
  201
  202 #define CONFIG_BOOTCOMMAND \
  203     "tftp 0x60003000 uImage; tftp 0x60500000 vexpress-v2p-ca9.dtb; \
  204     setenv bootargs 'root=/dev/nfs rw \
  205     nfsroot=192.168.5.129:/root/wlt/rootfs \
  206     ip=192.168.5.127 \
  207     init=/linuxrc console=ttyAMA0'; \
  208     bootm 0x60003000 - 0x60500000;"
  209
  210 #endif

启动

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

3. 完善rootfs

root@ubuntu:~/wlt/rootfs# cat etc/fstab
proc           /proc      proc    defaults   0     0
tmpfs          /tmp       tmpfs   defaults   0     0
sysfs          /sys       sysfs   defaults   0     0
var            /dev       tmpfs   defaults   0     0
ramfs          /dev       tmpfs   defaults   0     0

root@ubuntu:~/wlt/rootfs# cat 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

root@ubuntu:~/wlt/rootfs# cat etc/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"
echo "-----------------------------"


root@ubuntu:~/wlt/rootfs# cat etc/profile
PS1='yangxr@vexpress:\w # '
export PS1

4. 加载地址

以下面的地址为例

      "tftp 0x60000000 uImage; tftp 0x60500000 vexpress-v2p-ca9.dtb; \
      setenv bootargs 'root=/dev/nfs rw \
      nfsroot=192.168.5.129:/root/wlt/rootfs \
      ip=192.168.5.127 \
      init=/linuxrc console=ttyAMA0 \
      hello.num=10'; \
      bootm 0x60000000 - 0x60500000;"

uImage的大小:4.8MB
编译uImage的参数
make uImage LOADADDR=0x60002000
结合kernel的输出

## Booting kernel from Legacy Image at 60000000 ...
   Image Name:   Linux-5.16.2
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    5060064 Bytes = 4.8 MiB
   Load Address: 60002000
   Entry Point:  60002000
   Verifying Checksum ... OK
## Flattened Device Tree blob at 60500000
   Booting using the fdt blob at 0x60500000
   Loading Kernel Image ... OK
   Loading Device Tree to 7fef1000, end 7fef7700 ... OK

分析如下

所以使用 uImage 的好处之一,不论 tftp uImage到任意物理内存,uboot都会将uImage 重定位到 LOADADDR指定的地址。
这些地址理论上是任意的物理内存地址都可以用,注意uImage和 dtb 不要互相覆盖。

posted on 2022-07-31 11:46  开心种树  阅读(149)  评论(0编辑  收藏  举报