diff options
Diffstat (limited to 'meta/recipes-core/initrdscripts/initramfs-framework')
5 files changed, 142 insertions, 16 deletions
diff --git a/meta/recipes-core/initrdscripts/initramfs-framework/finish b/meta/recipes-core/initrdscripts/initramfs-framework/finish index 717383ebac..f08a920867 100755 --- a/meta/recipes-core/initrdscripts/initramfs-framework/finish +++ b/meta/recipes-core/initrdscripts/initramfs-framework/finish @@ -12,6 +12,18 @@ 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 /dev, /proc and /sys onto rootfs..." diff --git a/meta/recipes-core/initrdscripts/initramfs-framework/init b/meta/recipes-core/initrdscripts/initramfs-framework/init index c71ce0ce8c..567694aff7 100755 --- a/meta/recipes-core/initrdscripts/initramfs-framework/init +++ b/meta/recipes-core/initrdscripts/initramfs-framework/init @@ -88,12 +88,25 @@ 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 | 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/overlayroot b/meta/recipes-core/initrdscripts/initramfs-framework/overlayroot new file mode 100644 index 0000000000..d40342dc59 --- /dev/null +++ b/meta/recipes-core/initrdscripts/initramfs-framework/overlayroot @@ -0,0 +1,112 @@ +#!/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 'rootrw=<foo>' to be passed as a +# kernel parameter, specifying the device/partition intended to +# use as RW. +# +# 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" +} + + +if [ -z "$bootparam_rootrw" ]; then + exit_gracefully "rootrw= kernel parameter doesn't exist and its required to mount the overlayfs" +fi + +mkdir -p ${RWMOUNT} + +# Mount RW device +if mount -n -t ${bootparam_rootfstype:-ext4} -o ${bootparam_rootflags:-defaults} ${bootparam_rootrw} ${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 ee24e82af3..e0efbe6ebe 100644 --- a/meta/recipes-core/initrdscripts/initramfs-framework/rootfs +++ b/meta/recipes-core/initrdscripts/initramfs-framework/rootfs @@ -24,24 +24,13 @@ 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 + elif [ "`echo ${bootparam_root} | cut -c1-9`" = "PARTUUID=" ]; then root_partuuid=`echo $bootparam_root | cut -c10-` bootparam_root="/dev/disk/by-partuuid/$root_partuuid" - fi - - if [ "`echo ${bootparam_root} | cut -c1-10`" = "PARTLABEL=" ]; then - root_partlabel=`echo $bootparam_root | cut -c11-` - bootparam_root="/dev/disk/by-partlabel/$root_partlabel" - fi - - if [ "`echo ${bootparam_root} | cut -c1-10`" = "PARTLABEL=" ]; then + elif [ "`echo ${bootparam_root} | cut -c1-10`" = "PARTLABEL=" ]; then root_partlabel=`echo $bootparam_root | cut -c11-` bootparam_root="/dev/disk/by-partlabel/$root_partlabel" - fi - - if [ "`echo ${bootparam_root} | cut -c1-6`" = "LABEL=" ]; then + 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 @@ -67,8 +56,8 @@ rootfs_run() { # 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 |