[OE-core] [PATCH] core-image-minimal-initramfs: prepare initramfs for NFS boot

Oleksii Konoplitskyi okonopli at cisco.com
Mon Mar 12 14:33:07 UTC 2018


It helps to boot device by mounting rootfs via NFS when network
drivers are built as modules.
We include modules in core-image-minimal-initramfs image
and start kernel with specifying custom rdinit in cmdline:
   rdinit=/init-nfs.sh

NFS and IP parameters should be passed to kernel as usual.
For example:
   ip=192.168.0.11::192.168.0.1:255.255.255.0:linux:eth0:off
   nfsroot=192.168.0.10:/exported_nfs,nfsvers=3,tcp
   root=/dev/nfs rw loglevel=7 rdinit=/init-nfs.sh

To use this initramfs, one could put the following
to conf/local.conf:
   INITRAMFS_LOAD_KERNEL_MODULES = "kernel-module-igb"
   INITRAMFS_IMAGE_BUNDLE = "1"
   INITRAMFS_IMAGE = "core-image-minimal-initramfs"

INITRAMFS_LOAD_KERNEL_MODULES is a space-separated list of
modules that will be added to initramfs.

Signed-off-by: Andrii Bordunov <aborduno at cisco.com>
Signed-off-by: Oleksii Konoplitskyi <okonopli at cisco.com>
---
 .../images/core-image-minimal-initramfs.bb         |   2 +-
 meta/recipes-core/initrdscripts/files/init-nfs.sh  | 108 +++++++++++++++++++++
 .../initrdscripts/initramfs-nfs-boot_1.0.bb        |  14 +++
 3 files changed, 123 insertions(+), 1 deletion(-)
 create mode 100644 meta/recipes-core/initrdscripts/files/init-nfs.sh
 create mode 100644 meta/recipes-core/initrdscripts/initramfs-nfs-boot_1.0.bb

diff --git a/meta/recipes-core/images/core-image-minimal-initramfs.bb b/meta/recipes-core/images/core-image-minimal-initramfs.bb
index c446e87..bf794bf 100644
--- a/meta/recipes-core/images/core-image-minimal-initramfs.bb
+++ b/meta/recipes-core/images/core-image-minimal-initramfs.bb
@@ -3,7 +3,7 @@ DESCRIPTION = "Small image capable of booting a device. The kernel includes \
 the Minimal RAM-based Initial Root Filesystem (initramfs), which finds the \
 first 'init' program more efficiently."
 
-PACKAGE_INSTALL = "initramfs-live-boot initramfs-live-install initramfs-live-install-efi ${VIRTUAL-RUNTIME_base-utils} udev base-passwd ${ROOTFS_BOOTSTRAP_INSTALL}"
+PACKAGE_INSTALL = "initramfs-live-boot initramfs-live-install initramfs-live-install-efi ${VIRTUAL-RUNTIME_base-utils} udev base-passwd ${ROOTFS_BOOTSTRAP_INSTALL} initramfs-nfs-boot"
 
 # Do not pollute the initrd image with rootfs features
 IMAGE_FEATURES = ""
diff --git a/meta/recipes-core/initrdscripts/files/init-nfs.sh b/meta/recipes-core/initrdscripts/files/init-nfs.sh
new file mode 100644
index 0000000..31a55ec
--- /dev/null
+++ b/meta/recipes-core/initrdscripts/files/init-nfs.sh
@@ -0,0 +1,108 @@
+#!/bin/sh
+
+CONSOLE="/dev/console"
+PATH=/sbin:/bin:/usr/sbin:/usr/bin
+ROOT_MOUNT="/rootfs"
+
+fatal()
+{
+	echo $1 >$CONSOLE
+	echo >$CONSOLE
+	exec sh
+}
+
+net_up()
+{
+	[ "$(ifconfig $PARAM_IFNAME | awk '/inet addr/{print substr($2,6)}')" = "$PARAM_IP" ] && return
+	#load all ethernet drivers if network interface is not configured
+	MODULES="$(find /lib/modules/*/kernel/drivers/net/ethernet -name \*.ko | sed -e 's,^.*/,,' -e 's,\.ko$,,')"
+	[ -z "$MODULES" ] && fatal "Ethernet drivers list is emty. Nothing to load."
+	modprobe -a $MODULES
+
+	ifconfig $PARAM_IFNAME $PARAM_IP netmask $PARAM_NETMASK ||
+		fatal "Failed to configure ethernet interface"
+	route add default gw $PARAM_GW ||
+		fatal "Failed to set default gateway"
+}
+
+
+#TODO: IPv6 is not supported yet
+mount_nfs()
+{
+	mkdir $ROOT_MOUNT
+	for i in $(seq 1 10)
+	do
+		mount -t nfs "$PARAM_NFSROOT_PATH" -o nolock,"$PARAM_NFSROOT_OPTS" $ROOT_MOUNT && return
+		sleep 1
+	done
+	fatal "Could not mount rootfs via nfs"
+}
+
+
+early_setup()
+{
+	mkdir -p /proc
+	mkdir -p /sys
+	mount -t proc proc /proc
+	mount -t sysfs sysfs /sys
+	mount -t devtmpfs none /dev
+
+	mkdir -p /run
+	mkdir -p /var/run
+}
+
+
+#TODO: IPv6 is not supported yet
+read_args()
+{
+	[ -z "$CMDLINE" ] && CMDLINE=$(cat /proc/cmdline)
+	for arg in $CMDLINE; do
+		optarg=$(expr "x$arg" : 'x[^=]*=\(.*\)'$)
+		case $arg in
+		ip=*)
+			PARAM_IFNAME=$(echo "$optarg" | cut -d: -f6)
+			PARAM_IP_ALL=$(echo "$optarg" | grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}')
+			PARAM_IP=$(echo "$PARAM_IP_ALL" | sed -n 1p)
+			PARAM_GW=$(echo "$PARAM_IP_ALL" | sed -n 2p)
+			PARAM_NETMASK=$(echo "$PARAM_IP_ALL" | sed -n 3p)
+			;;
+		nfsroot=*)
+			PARAM_NFSROOT_PATH=$(echo "$optarg" | cut -d, -f1)
+			PARAM_NFSROOT_OPTS=$(echo "$optarg" | cut -d, -f2-)
+			;;
+		debugshell)
+			DEBUGSHELL=1
+			;;
+		esac
+	done
+}
+
+boot_nfs()
+{
+	touch $ROOT_MOUNT/bin || fatal "Rootfs is not writeable"
+
+	mount -n --move /proc ${ROOT_MOUNT}/proc
+	mount -n --move /sys ${ROOT_MOUNT}/sys
+	mount -n --move /dev ${ROOT_MOUNT}/dev
+
+	cd $ROOT_MOUNT
+
+	# busybox switch_root supports -c option
+	exec switch_root -c /dev/console $ROOT_MOUNT /sbin/init $CMDLINE ||
+		fatal "Couldn't switch_root, dropping to shell"
+}
+
+early_setup
+
+read_args
+
+if [ -n "$DEBUGSHELL" ]; then
+	exec sh
+fi
+
+net_up
+
+mount_nfs
+
+boot_nfs
+
diff --git a/meta/recipes-core/initrdscripts/initramfs-nfs-boot_1.0.bb b/meta/recipes-core/initrdscripts/initramfs-nfs-boot_1.0.bb
new file mode 100644
index 0000000..ca4f191
--- /dev/null
+++ b/meta/recipes-core/initrdscripts/initramfs-nfs-boot_1.0.bb
@@ -0,0 +1,14 @@
+SUMMARY = "Live image init script"
+LICENSE = "MIT"
+LIC_FILES_CHKSUM = "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420"
+RDEPENDS_${PN} = "${@['', d.getVar('INITRAMFS_LOAD_KERNEL_MODULES', True)][d.getVar('INITRAMFS_LOAD_KERNEL_MODULES', True) is not None]}"
+SRC_URI = "file://init-nfs.sh"
+
+S = "${WORKDIR}"
+
+do_install() {
+        install -m 0755 ${WORKDIR}/init-nfs.sh ${D}/init-nfs.sh
+}
+
+FILES_${PN} += " /init-nfs.sh "
+
-- 
2.7.4




More information about the Openembedded-core mailing list