summaryrefslogtreecommitdiffstats
path: root/meta/recipes-core/initrdscripts/initramfs-framework
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-core/initrdscripts/initramfs-framework')
-rw-r--r--meta/recipes-core/initrdscripts/initramfs-framework/exec29
-rwxr-xr-xmeta/recipes-core/initrdscripts/initramfs-framework/finish21
-rwxr-xr-xmeta/recipes-core/initrdscripts/initramfs-framework/init20
-rw-r--r--meta/recipes-core/initrdscripts/initramfs-framework/lvm13
-rw-r--r--meta/recipes-core/initrdscripts/initramfs-framework/nfsrootfs48
-rw-r--r--meta/recipes-core/initrdscripts/initramfs-framework/overlayroot118
-rw-r--r--meta/recipes-core/initrdscripts/initramfs-framework/rootfs20
-rw-r--r--meta/recipes-core/initrdscripts/initramfs-framework/setup-live2
-rw-r--r--meta/recipes-core/initrdscripts/initramfs-framework/udev4
9 files changed, 265 insertions, 10 deletions
diff --git a/meta/recipes-core/initrdscripts/initramfs-framework/exec b/meta/recipes-core/initrdscripts/initramfs-framework/exec
new file mode 100644
index 0000000000..a8e2432bb6
--- /dev/null
+++ b/meta/recipes-core/initrdscripts/initramfs-framework/exec
@@ -0,0 +1,29 @@
+#!/bin/sh
+# Copyright (C) 2017 O.S. Systems Software LTDA.
+# Licensed on MIT
+
+EXEC_DIR=/exec.d # place to look for modules
+
+exec_enabled() {
+ return 0
+}
+
+exec_run() {
+ if [ ! -d $EXEC_DIR ]; then
+ msg "No contents to exec in $EXEC_DIR. Starting shell ..."
+ sh
+ fi
+
+ # Load and run modules
+ for m in $EXEC_DIR/*; do
+ # Skip backup files
+ if [ "`echo $m | sed -e 's/\~$//'`" != "$m" ]; then
+ continue
+ fi
+
+ debug "Starting $m"
+
+ # process module
+ ./$m
+ done
+}
diff --git a/meta/recipes-core/initrdscripts/initramfs-framework/finish b/meta/recipes-core/initrdscripts/initramfs-framework/finish
index 717383ebac..ac0de9f996 100755
--- a/meta/recipes-core/initrdscripts/initramfs-framework/finish
+++ b/meta/recipes-core/initrdscripts/initramfs-framework/finish
@@ -12,8 +12,29 @@ finish_run() {
fatal "ERROR: There's no '/dev' on rootfs."
fi
+ # Unmount anything that was automounted by busybox via mdev-mount.sh.
+ # We're about to switch_root, and leaving anything mounted will prevent
+ # the next rootfs from modifying the block device. Ignore ROOT_DISK,
+ # if it was set by setup-live, because it'll be mounted over loopback
+ # to ROOTFS_DIR.
+ local dev
+ for dev in /run/media/*; do
+ if mountpoint -q "${dev}" && [ "${dev##*/}" != "${ROOT_DISK}" ]; then
+ umount -f "${dev}" || debug "Failed to unmount ${dev}"
+ fi
+ done
+
info "Switching root to '$ROOTFS_DIR'..."
+ debug "Moving basic mounts onto rootfs"
+ for dir in `awk '/\/dev.* \/run\/media/{print $2}' /proc/mounts`; do
+ # Parse any OCT or HEX encoded chars such as spaces
+ # in the mount points to actual ASCII chars
+ dir=`printf $dir`
+ mkdir -p "${ROOTFS_DIR}/media/${dir##*/}"
+ mount -n --move "$dir" "${ROOTFS_DIR}/media/${dir##*/}"
+ done
+
debug "Moving /dev, /proc and /sys onto rootfs..."
mount --move /dev $ROOTFS_DIR/dev
mount --move /proc $ROOTFS_DIR/proc
diff --git a/meta/recipes-core/initrdscripts/initramfs-framework/init b/meta/recipes-core/initrdscripts/initramfs-framework/init
index 37527a840a..567694aff7 100755
--- a/meta/recipes-core/initrdscripts/initramfs-framework/init
+++ b/meta/recipes-core/initrdscripts/initramfs-framework/init
@@ -72,6 +72,7 @@ ROOTFS_DIR="/rootfs" # where to do the switch root
MODULE_PRE_HOOKS="" # functions to call before running each module
MODULE_POST_HOOKS="" # functions to call after running each module
MODULES_DIR=/init.d # place to look for modules
+EFI_DIR=/sys/firmware/efi # place to store device firmware information
# make mount stop complaining about missing /etc/fstab
touch /etc/fstab
@@ -81,14 +82,31 @@ mkdir -p /proc /sys /run/lock /var/lock
mount -t proc proc /proc
mount -t sysfs sysfs /sys
+if [ -d $EFI_DIR ];then
+ mount -t efivarfs none /sys/firmware/efi/efivars
+fi
+
# populate bootparam environment
for p in `cat /proc/cmdline`; do
+ if [ -n "$quoted" ]; then
+ value="$value $p"
+ if [ "`echo $p | sed -e 's/\"$//'`" != "$p" ]; then
+ eval "bootparam_${quoted}=${value}"
+ unset quoted
+ fi
+ continue
+ fi
+
opt=`echo $p | cut -d'=' -f1`
- opt=`echo $opt | tr '.-' '__'`
+ opt=`echo $opt | sed -e 'y/.-/__/'`
if [ "`echo $p | cut -d'=' -f1`" = "$p" ]; then
eval "bootparam_${opt}=true"
else
value="`echo $p | cut -d'=' -f2-`"
+ if [ "`echo $value | sed -e 's/^\"//'`" != "$value" ]; then
+ quoted=${opt}
+ continue
+ fi
eval "bootparam_${opt}=\"${value}\""
fi
done
diff --git a/meta/recipes-core/initrdscripts/initramfs-framework/lvm b/meta/recipes-core/initrdscripts/initramfs-framework/lvm
new file mode 100644
index 0000000000..7deeccb9a2
--- /dev/null
+++ b/meta/recipes-core/initrdscripts/initramfs-framework/lvm
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+lvm_enabled() {
+ if ! lvscan |grep -i -w "inactive" &>/dev/null;then
+ return 1
+ fi
+ return 0
+}
+
+lvm_run() {
+ lvm pvscan --cache --activate ay
+ udevadm trigger --action=add
+}
diff --git a/meta/recipes-core/initrdscripts/initramfs-framework/nfsrootfs b/meta/recipes-core/initrdscripts/initramfs-framework/nfsrootfs
new file mode 100644
index 0000000000..e67ee4c25d
--- /dev/null
+++ b/meta/recipes-core/initrdscripts/initramfs-framework/nfsrootfs
@@ -0,0 +1,48 @@
+#!/bin/sh
+
+nfsrootfs_enabled() {
+ if [ ${bootparam_root} != "/dev/nfs" ] || [ -z ${bootparam_nfsroot} ]; then
+ return 1
+ fi
+ return 0
+}
+
+nfsrootfs_run() {
+ local nfs_opts
+ local location
+ local flags
+ local server_ip
+
+ nfs_opts=""
+ if [ "${bootparam_nfsroot#*,}" != "${bootparam_nfsroot}" ]; then
+ nfs_opts="-o ${bootparam_nfsroot#*,}"
+ fi
+
+ location="${bootparam_nfsroot%%,*}"
+ if [ "${location#*:}" = "${location}" ]; then
+ # server-ip not given. Get server ip from ip option
+ server_ip=""
+ if [ "${bootparam_ip#*:}" != "${bootparam_ip}" ]; then
+ server_ip=$(echo "$bootparam_ip" | cut -d: -f2)
+ fi
+
+ if [ -z "$server_ip" ]; then
+ fatal "Server IP is not set. Update ip or nfsroot options."
+ fi
+ location=${server_ip}:${location}
+ fi
+
+ flags="-o nolock"
+ if [ -n "$bootparam_ro" ] && ! echo "$bootparam_rootflags" | grep -w -q "ro"; then
+ if [ -n "$bootparam_rootflags" ]; then
+ bootparam_rootflags="$bootparam_rootflags,"
+ fi
+ bootparam_rootflags="${bootparam_rootflags}ro"
+ fi
+ if [ -n "$bootparam_rootflags" ]; then
+ flags="$flags -o $bootparam_rootflags"
+ fi
+
+ mount -t nfs ${flags} ${nfs_opts} ${location} ${ROOTFS_DIR}
+}
+
diff --git a/meta/recipes-core/initrdscripts/initramfs-framework/overlayroot b/meta/recipes-core/initrdscripts/initramfs-framework/overlayroot
new file mode 100644
index 0000000000..0d41432878
--- /dev/null
+++ b/meta/recipes-core/initrdscripts/initramfs-framework/overlayroot
@@ -0,0 +1,118 @@
+#!/bin/sh
+
+# SPDX-License-Identifier: MIT
+#
+# Copyright 2022 (C), Microsoft Corporation
+
+# Simple initramfs module intended to mount a read-write (RW)
+# overlayfs on top of /, keeping the original root filesystem
+# as read-only (RO), free from modifications by the user.
+#
+# NOTE: The read-only IMAGE_FEATURE is not required for this to work
+#
+# This script is based on the overlay-etc.bbclass, which sets up
+# an overlay on top of the /etc directory, but in this case allows
+# accessing the original, unmodified rootfs at /rofs after boot.
+#
+# It relies on the initramfs-module-rootfs to mount the original
+# root filesystem, and requires 'overlayrootrwdev=<foo>' to be passed as a
+# kernel parameter, specifying the device/partition intended to
+# use as RW.
+# Mount options of the RW device can be tweaked with 'overlayrootfstype='
+# (defaults to 'ext4') and 'overlayrootfsflags=' ('defaults').
+#
+# This module needs to be executed after the initramfs-module-rootfs
+# since it relies on it to mount the filesystem at initramfs startup
+# but before the finish module which normally switches root.
+# After overlayroot is executed the usual boot flow continues from
+# the real init process.
+#
+# If something goes wrong while running this module, the rootfs
+# is still mounted RO (with no overlay) and the finish module is
+# executed to continue booting normally.
+#
+# It also has a dependency on overlayfs being enabled in the
+# running kernel via KERNEL_FEATURES (kmeta) or any other means.
+
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin
+
+# We get OLDROOT from the rootfs module
+OLDROOT="/rootfs"
+
+NEWROOT="${RWMOUNT}/root"
+RWMOUNT="/overlay"
+ROMOUNT="${RWMOUNT}/rofs"
+UPPER_DIR="${RWMOUNT}/upper"
+WORK_DIR="${RWMOUNT}/work"
+
+MODULES_DIR=/init.d
+
+# Something went wrong, make sure / is mounted as read only anyway.
+exit_gracefully() {
+ echo $1 >/dev/console
+ echo >/dev/console
+ echo "OverlayRoot mounting failed, starting system as read-only" >/dev/console
+ echo >/dev/console
+
+ # The following is borrowed from rootfs-postcommands.bbclass
+ # This basically looks at the real rootfs mounting options and
+ # replaces them with "ro"
+
+ # Tweak the mount option and fs_passno for rootfs in fstab
+ if [ -f ${OLDROOT}/etc/fstab ]; then
+ sed -i -e '/^[#[:space:]]*\/dev\/root/{s/defaults/ro/;s/\([[:space:]]*[[:digit:]]\)\([[:space:]]*\)[[:digit:]]$/\1\20/}' ${OLDROOT}/etc/fstab
+ fi
+
+ # Tweak the "mount -o remount,rw /" command in busybox-inittab inittab
+ if [ -f ${OLDROOT}/etc/inittab ]; then
+ sed -i 's|/bin/mount -o remount,rw /|/bin/mount -o remount,ro /|' ${OLDROOT}/etc/inittab
+ fi
+
+ # Continue as if the overlayroot module didn't exist to continue booting
+ . $MODULES_DIR/99-finish
+ eval "finish_run"
+}
+
+# migrate legacy parameter
+if [ ! -z "$bootparam_rootrw" ]; then
+ bootparam_overlayrootrwdev="$bootparam_rootrw"
+fi
+
+if [ -z "$bootparam_overlayrootrwdev" ]; then
+ exit_gracefully "overlayrootrwdev= kernel parameter doesn't exist and its required to mount the overlayfs"
+fi
+
+mkdir -p ${RWMOUNT}
+
+# Mount RW device
+if mount -n -t ${bootparam_overlayrootfstype:-ext4} -o ${bootparam_overlayrootfsflags:-defaults} ${bootparam_overlayrootrwdev} ${RWMOUNT}
+then
+ # Set up overlay directories
+ mkdir -p ${UPPER_DIR}
+ mkdir -p ${WORK_DIR}
+ mkdir -p ${NEWROOT}
+ mkdir -p ${ROMOUNT}
+
+ # Remount OLDROOT as read-only
+ mount -o bind ${OLDROOT} ${ROMOUNT}
+ mount -o remount,ro ${ROMOUNT}
+
+ # Mount RW overlay
+ mount -t overlay overlay -o lowerdir=${ROMOUNT},upperdir=${UPPER_DIR},workdir=${WORK_DIR} ${NEWROOT} || exit_gracefully "initramfs-overlayroot: Mounting overlay failed"
+else
+ exit_gracefully "initramfs-overlayroot: Mounting RW device failed"
+fi
+
+# Set up filesystems on overlay
+mkdir -p ${NEWROOT}/proc
+mkdir -p ${NEWROOT}/dev
+mkdir -p ${NEWROOT}/sys
+mkdir -p ${NEWROOT}/rofs
+
+mount -n --move ${ROMOUNT} ${NEWROOT}/rofs
+mount -n --move /proc ${NEWROOT}/proc
+mount -n --move /sys ${NEWROOT}/sys
+mount -n --move /dev ${NEWROOT}/dev
+
+exec chroot ${NEWROOT}/ ${bootparam_init:-/sbin/init} || exit_gracefully "Couldn't chroot into overlay"
diff --git a/meta/recipes-core/initrdscripts/initramfs-framework/rootfs b/meta/recipes-core/initrdscripts/initramfs-framework/rootfs
index 14768f1cd4..e0efbe6ebe 100644
--- a/meta/recipes-core/initrdscripts/initramfs-framework/rootfs
+++ b/meta/recipes-core/initrdscripts/initramfs-framework/rootfs
@@ -13,7 +13,7 @@ rootfs_run() {
C=0
delay=${bootparam_rootdelay:-1}
timeout=${bootparam_roottimeout:-5}
- while [ ! -d $ROOTFS_DIR/dev ]; do
+ while ! mountpoint -q $ROOTFS_DIR; do
if [ $(( $C * $delay )) -gt $timeout ]; then
fatal "root '$bootparam_root' doesn't exist or does not contain a /dev."
fi
@@ -24,11 +24,15 @@ rootfs_run() {
if [ "`echo ${bootparam_root} | cut -c1-5`" = "UUID=" ]; then
root_uuid=`echo $bootparam_root | cut -c6-`
bootparam_root="/dev/disk/by-uuid/$root_uuid"
- fi
-
- if [ "`echo ${bootparam_root} | cut -c1-9`" = "PARTUUID=" ]; then
- root_uuid=`echo $bootparam_root | cut -c10-`
- bootparam_root="/dev/disk/by-partuuid/$root_uuid"
+ elif [ "`echo ${bootparam_root} | cut -c1-9`" = "PARTUUID=" ]; then
+ root_partuuid=`echo $bootparam_root | cut -c10-`
+ bootparam_root="/dev/disk/by-partuuid/$root_partuuid"
+ elif [ "`echo ${bootparam_root} | cut -c1-10`" = "PARTLABEL=" ]; then
+ root_partlabel=`echo $bootparam_root | cut -c11-`
+ bootparam_root="/dev/disk/by-partlabel/$root_partlabel"
+ elif [ "`echo ${bootparam_root} | cut -c1-6`" = "LABEL=" ]; then
+ root_label=`echo $bootparam_root | cut -c7-`
+ bootparam_root="/dev/disk/by-label/$root_label"
fi
if [ -e "$bootparam_root" ]; then
@@ -46,14 +50,14 @@ rootfs_run() {
flags="$flags -t$bootparam_rootfstype"
fi
mount $flags $bootparam_root $ROOTFS_DIR
- if [ -d $ROOTFS_DIR/dev ]; then
+ if mountpoint -q $ROOTFS_DIR; then
break
else
# It is unlikely to change, but keep trying anyway.
# Perhaps we pick a different device next time.
umount $ROOTFS_DIR
- fi
fi
+ fi
fi
debug "Sleeping for $delay second(s) to wait root to settle..."
sleep $delay
diff --git a/meta/recipes-core/initrdscripts/initramfs-framework/setup-live b/meta/recipes-core/initrdscripts/initramfs-framework/setup-live
index 4c79f41285..7e92f93322 100644
--- a/meta/recipes-core/initrdscripts/initramfs-framework/setup-live
+++ b/meta/recipes-core/initrdscripts/initramfs-framework/setup-live
@@ -1,4 +1,4 @@
-#/bin/sh
+#!/bin/sh
# Copyright (C) 2011 O.S. Systems Software LTDA.
# Licensed on MIT
diff --git a/meta/recipes-core/initrdscripts/initramfs-framework/udev b/meta/recipes-core/initrdscripts/initramfs-framework/udev
index 79c8867823..4898b89246 100644
--- a/meta/recipes-core/initrdscripts/initramfs-framework/udev
+++ b/meta/recipes-core/initrdscripts/initramfs-framework/udev
@@ -6,6 +6,7 @@ udev_shutdown_hook_handler() {
status=$1
module=$2
if [ "$status" = "pre" ] && [ "$module" = "finish" ]; then
+ udevadm settle
killall `basename $_UDEV_DAEMON` 2>/dev/null
fi
}
@@ -40,6 +41,9 @@ udev_run() {
mkdir -p /run
mkdir -p /var/run
+ # Workaround if console=null, systemd-udevd needs valid stdin, stdout and stderr to work
+ sh -c "exec 4< /dev/console" || { exec 0> /dev/null; exec 1> /dev/null; exec 2> /dev/null; }
+
$_UDEV_DAEMON --daemon
udevadm trigger --action=add
udevadm settle