目录
前言
根文件系统(rootfs)是内核启动时所挂载的第一个文件系统,内核代码映像文件保存在根文件系统中,而系统引导启动程序会在根文件系统挂载之后从中把一些基本的初始化脚本和服务等加载到内存中去运行。根文件系统中所需要的大部分linux命令和工具软件可通过busybox来构建,简化了构建根文件系统的复杂度。
本次移植rootfs的软硬件环境环境如下:
主机环境:Ubuntu 18.04.4 LTS
编译环境:arm-linux-gcc-4.3.2
构建工具:busybox-1.25
目标机:飞凌-OK6410-A
引导加载程序:uboot-1.1.6
一、创建根文件系统目录
在主机上创建一个临时目录,将最终文件汇编并转移到目录机上,本文使用~/rootfs目录,通过运行脚本(build_rootfs.sh)来创建根文件系统目录,脚本内容如下:
#!/bin/sh
# Create rootfs directory and enter
mkdir ~/rootfs
cd ~/rootfs
# Create a first level directory under rootfs
mkdir bin dev etc home lib proc sbin sys tmp usr var
# Create a secondary directory under rootfs
mkdir usr/bin usr/lib usr/sbin
mkdir var/log
mkdir etc/init.d
二、添加命令与实用程序
busybox是一系列小程序的集合,主要功能是调用基于命令行参数的对应程序。
2.1 编译和安装 busybox
1、下载busybox-1.25
Busybox官网下载地址:https://busybox.net,找到“ BusyBox 1.25.0”链接并下载。
2、解压busybox
进入下载包所在的目录,解压如下:
# Create a temporary directory
mkdir ~/tmp
# Extract the installation source file
tar -jxvf busybox-1.25.0.tar.bz2 -C ~/tmp
3、 配置busybox
(1)修改 Makefile
进入busybox-1.25.0目录,修改Makefile文件内容,
1、将 CROSS_COMPILE ?= 改为:CROSS_COMPILE ?= arm-linux-
2、将 ARCH ?= $(SUBARCH) 改为:ARCH ?= arm
也可以直接编写脚本(edit_makefile.sh)实现Makefile内容的修改,如下:
#! /bin/sh
# Configure ARCH and CROSS_COMPILE
sed -i "s/ARCH ?= \$(SUBARCH)/ARCH ?= arm/g" ~/tmp/busybox-1.25.0/Makefile
sed -i "s/CROSS_COMPILE ?=/CROSS_COMPILE ?= arm-linux-/g" ~/tmp/busybox-1.25.0/Makefile
(2)图像化界面配置
进入“tmp/busybox-1.25.0”,源目录,运行“make menuconfig”,并进行配置,主要修改如下:
Linux Module Utilities --->
全选(*)
Busybox Setting --->
Installation Options ("make install" behavior) --->
(./_install) BusyBox installation prefix
Build Options --->
选择[*]Build Busybox as a static binary(no shared libs)
Linux System Utilities --->
去掉选项[ ]nsenter
Coreutils --->
去掉选项[ ]sync
(3)添加fs.h头文件
将文件“/usr/include/linux/fs.h”拷贝目录“~/tmp/busybox-1.25.0/include/”,并在“~/tmp/busybox-1.25.0/util-linux/blkdiscard.c”中添加头文件声明“#include "fs.h”,否则,出现错误“util-linux/blkdiscard.c:72: error: 'BLKSECDISCARD' undeclared (first use in this function)”。
(4)添加mtd-abi.h头文件
将文件“/usr/include/mtd/mtd-abi.h”拷贝目录“~/tmp/busybox-1.25.0/include/”,并在“~/tmp/busybox-1.25.0/util-linux/blkdiscard.c”中添加头文件声明“#include "mtd-abi.h”,否则,出现错误“miscutils/nandwrite.c:151: error: 'MTD_FILE_MODE_RAW' undeclared (first use in this function)”。
4、 编译与安装
make & make install
2.2 拷贝busybox内的小程序
cp -rfd ~/tmp/busybox-1.25.0/_install/* ~/rootfs
三、添加lib库文件
由于Linux在运行应用程序时需要一些lib库,所以需要拷贝工具链内的动态lib库文件到“~/rootfs/lib”和静态库文件到“~/rootfs/usr/lib”。
3.1 拷贝工具链内的动态库
# Copy the dynamic library files used by system programs
cp -d /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/lib/*so* ~/rootfs/lib/
3.2 拷贝工具链内的静态库
# Copy the static library files used by user programs
cp -d /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/lib/*.a ~/rootfs/usr/lib/
四、其它相关配置
4.1 创建文件inittab
inittab为linux初始化文件系统时init初始化程序用到的配置文件,这个文件负责:
- 设置init初始化程序初始化脚本在哪里;
- 每个运行级初始化时运行的命令;
- 开机、关机、重启对应的命令;
- 各运行级登录时所运行的命令;
使用命令创建“inittab”文件:
touch ~/rootfs/etc/inittab
“~/rootfs/etc/inittab”文件的内容如下:
#this is run first except when booting in single-user mode.
::sysinit:/etc/init.d/rcS
# /bin/sh invocations on selected ttys
::respawn:-/bin/sh
# Start an "askfirst" shell on the console (whatever that may be)
::askfirst:-/bin/sh
# Stuff to do when restarting the init process
::restart:/sbin/init
# Stuff to do before rebooting
::ctrlaltdel:/sbin/reboot
::shutdown:/sbin/swapoff -a
4.2 创建文件/etc/init.d/rcS
rcS是一个脚本文件,在inittab文件中本解析调用,用于配置Linux系统,使用命令创建“rcS”文件:
touch ~/rootfs/etc/init.d/rcS
“~/rootfs/etc/init.d/rcS”文件的内容如下:
#!/bin/sh
#This is the first script called by init process
/bin/mount -a
echo /sbin/mdev>/proc/sys/kernel/hotplug
mdev -s
设置rcS文件权限,如下:
chmod 755 ~/rootfs/etc/init.d/rcS
4.3 创建文件etc/fstab
“fastab”文件用于描述系统中各种文件系统的信息,使用命令创建“fstab”文件:
touch ~/rootfs/etc/fstab
“~/rootfs/etc/fstab”文件的内容如下:
#device mount-point type options dump fsck order
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
4.4 创建/etc/profile
“profile”文件用于配置系统环境变量,使用命令创建“profile”文件:
touch ~/rootfs/etc/profile
“~/rootfs/etc/profile”文件的内容如下:
#!/bin/sh
export HOSTNAME=ok6410
export USER=root
export HOME=root
export PS1="[$USER@$HOSTNAME \W]\# "
#export PS1="[\[\033[01;32m\]$USER@\[\033[00m\]\[\033[01;34m\]$HOSTNAME\[\033[00m\ \W]\$ "
PATH=/bin:/sbin:/usr/bin:/usr/sbin
LD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATH
export PATH LD_LIBRARY_PATH
4.5 添加设备节点
在根文件目录下添加“/dev/null”空设备和“/dev/console”虚拟设备,命令内容如下:
sudo mknod -m 666 ~/rootfs/dev/null c 1 3
sudo mknod -m 600 ~/rootfs/dev/console c 5 1
五、使用NFS挂载linux根文件系统
5.1 配置uboot环境变量
开机启动后进入uboot,环境变量的配置打印如下:
SMDK6410 # printenv
bootcmd=nand read 0xc0008000 0x200000 0x500000;bootm 0xc0008000
bootdelay=1
baudrate=115200
ethaddr=00:40:5c:26:0a:5b
netmask=255.255.255.0
ipaddr=192.168.1.110
serverip=192.168.1.103
gatewayip=192.168.1.1
bootargs=root=/dev/nfs nfsroot=192.168.1.103:/home/daniel/nfs/rootfs ip=192.168.1.110:192.168.1.103:192.168.1.1:255.255.255.0::eth0:off console=ttySAC0,115200 init=/linuxrc
stdin=serial
stdout=serial
stderr=serial
5.2 搭建NFS服务器
(1)安装NFS服务
apt-get install nfs-common nfs-kernel-server
(2)创建共享目录
修改“/etc/exports”,添加目录并配置权限
/home/daniel/rootfs *(rw,sync,no_root_squash,no_subtree_check)
(3)配置NFS协议
因为Ubuntu18.04的NFS默认支持协议3和协议4,而目标机的uboot默认启动的是NFS协议2,所以需要配置“/etc/default/nfs-kernel-server”文件,在文件最后添加一行配置信息,如下:
RPCNFSDOPTS="--nfs-version 2,3,4 --debug --syslog"
若是配置为NFS协议2,则出现如下错误:
ALSA device list:
#0: smdk6410
TCP cubic registered
NET: Registered protocol family 17
can: controller area network core (rev 20090105 abi 8)
NET: Registered protocol family 29
can: raw protocol (rev 20090105)
can: broadcast manager protocol (rev 20090105 t)
lib80211: common routines for IEEE802.11 drivers
Registering the dns_resolver key type
s3c-rtc s3c64xx-rtc: setting system clock to 2022-07-24 16:32:19 UTC (1658680339)
dm9000 dm9000.0: eth0: link down
dm9000 dm9000.0: eth0: link up, 100Mbps, full-duplex, lpa 0x45E1
VFS: Unable to mount root fs via NFS, trying floppy.
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(2,0)
[<c003aca8>] (unwind_backtrace+0x0/0xfc) from [<c04a8330>] (dump_stack+0x18/0x1c)
[<c04a8330>] (dump_stack+0x18/0x1c) from [<c04a8394>] (panic+0x60/0x1ac)
[<c04a8394>] (panic+0x60/0x1ac) from [<c0008fd0>] (mount_block_root+0x204/0x25c)
[<c0008fd0>] (mount_block_root+0x204/0x25c) from [<c00090b0>] (mount_root+0x88/0xd0)
[<c00090b0>] (mount_root+0x88/0xd0) from [<c0009204>] (prepare_namespace+0x10c/0x1a8)
[<c0009204>] (prepare_namespace+0x10c/0x1a8) from [<c00084c4>] (kernel_init+0xf0/0x130)
[<c00084c4>] (kernel_init+0xf0/0x130) from [<c0035a34>] (kernel_thread_exit+0x0/0x8)
(4)重启NFS服务
/etc/init.d/nfs-kernel-server restart
总结
使用NFS挂载linux根文件系统时,报错“VFS: Unable to mount root fs via NFS, trying floppy”,使自己一度陷入困惑,最终定位到是NFS服务器配置的问题,这种错误是好像是每二次出现了,真是有点不长记性了。@_@