From 2a1649095d73a1e247c86ba7bc7e08478746aa48 Mon Sep 17 00:00:00 2001
From: j1nx
Date: Sun, 23 Feb 2025 07:12:39 +0000
Subject: [PATCH] Another try for dracut-ng
---
buildroot | 2 +-
buildroot-external/configs/rpi4_64_defconfig | 1 +
.../init-readonly-rootfs-overlay-boot.sh | 256 ++++++++++++++++++
.../99readonly-rootfs-overlay/module-setup.sh | 66 +++++
4 files changed, 324 insertions(+), 1 deletion(-)
create mode 100644 buildroot-external/dracut/modules.d/99readonly-rootfs-overlay/init-readonly-rootfs-overlay-boot.sh
create mode 100644 buildroot-external/dracut/modules.d/99readonly-rootfs-overlay/module-setup.sh
diff --git a/buildroot b/buildroot
index 5385cac2..6c5d0339 160000
--- a/buildroot
+++ b/buildroot
@@ -1 +1 @@
-Subproject commit 5385cac22324ab3209ffe919c1c283989baf3951
+Subproject commit 6c5d033914dad097685b7a419ae8ec14ee870c8c
diff --git a/buildroot-external/configs/rpi4_64_defconfig b/buildroot-external/configs/rpi4_64_defconfig
index a7a92f0d..6f5ad8cb 100644
--- a/buildroot-external/configs/rpi4_64_defconfig
+++ b/buildroot-external/configs/rpi4_64_defconfig
@@ -175,6 +175,7 @@ BR2_PACKAGE_ALSA_LIB_PYTHON=y
BR2_PACKAGE_ALSA_PLUGINS=y
BR2_PACKAGE_LIBSAMPLERATE=y
BR2_PACKAGE_LIBSNDFILE=y
+BR2_PACKAGE_RNNOISE=y
BR2_PACKAGE_LIBARCHIVE=y
BR2_PACKAGE_LIBDEFLATE=y
BR2_PACKAGE_LZO=y
diff --git a/buildroot-external/dracut/modules.d/99readonly-rootfs-overlay/init-readonly-rootfs-overlay-boot.sh b/buildroot-external/dracut/modules.d/99readonly-rootfs-overlay/init-readonly-rootfs-overlay-boot.sh
new file mode 100644
index 00000000..8011a9b1
--- /dev/null
+++ b/buildroot-external/dracut/modules.d/99readonly-rootfs-overlay/init-readonly-rootfs-overlay-boot.sh
@@ -0,0 +1,256 @@
+#!/bin/bash
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin
+
+MOUNT="/bin/mount"
+
+PREINIT=""
+INIT="/sbin/init"
+ROOT_ROINIT="/sbin/init"
+
+ROOT_MOUNT="/mnt"
+ROOT_RODEVICE=""
+ROOT_RWDEVICE=""
+ROOT_ROMOUNT="/media/rfs/ro"
+ROOT_RWMOUNT="/media/rfs/rw"
+ROOT_RWRESET="no"
+
+ROOT_ROFSTYPE=""
+ROOT_ROMOUNTOPTIONS="bind"
+ROOT_ROMOUNTOPTIONS_DEVICE="noatime,nodiratime"
+
+ROOT_RWFSTYPE=""
+ROOT_RWMOUNTOPTIONS="rw,noatime,mode=755 tmpfs"
+ROOT_RWMOUNTOPTIONS_DEVICE="rw,noatime,mode=755"
+
+early_setup() {
+ mkdir -p /proc
+ mkdir -p /sys
+ $MOUNT -t proc proc /proc
+ grep -w "/sys" /proc/mounts >/dev/null || $MOUNT -t sysfs sysfs /sys
+ grep -w "/dev" /proc/mounts >/dev/null || $MOUNT -t devtmpfs none /dev
+}
+
+probe_fs() {
+ # Determine if we need to probe any modules to support the filesystem
+ if ! grep -w "$1" /proc/filesystems >/dev/null; then
+ modprobe "$optarg" 2> /dev/null || \
+ log "Could not load $optarg module"
+ fi
+}
+
+read_args() {
+ [ -z "${CMDLINE+x}" ] && CMDLINE=$(cat /proc/cmdline)
+ for arg in $CMDLINE; do
+ # Set optarg to option parameter, and '' if no parameter was
+ # given
+ optarg=$(expr "x$arg" : 'x[^=]*=\(.*\)' || echo '')
+ case $arg in
+ root=*)
+ ROOT_RODEVICE=$optarg ;;
+ rootfstype=*)
+ ROOT_ROFSTYPE="$optarg"
+ probe_fs "$optarg" ;;
+ rootinit=*)
+ ROOT_ROINIT=$optarg ;;
+ rootoptions=*)
+ ROOT_ROMOUNTOPTIONS_DEVICE="$optarg" ;;
+ rootrw=*)
+ ROOT_RWDEVICE=$optarg ;;
+ rootrwfstype=*)
+ ROOT_RWFSTYPE="$optarg"
+ probe_fs "$optarg" ;;
+ rootrwreset=*)
+ ROOT_RWRESET=$optarg ;;
+ rootrwoptions=*)
+ ROOT_RWMOUNTOPTIONS_DEVICE="$optarg" ;;
+ overlayfstype=*)
+ modprobe "$optarg" 2> /dev/null || \
+ log "Could not load $optarg module";;
+ preinit=*)
+ PREINIT=$optarg ;;
+ init=*)
+ INIT=$optarg ;;
+ esac
+ done
+}
+
+fatal() {
+ echo "rorootfs-overlay: $1" > "$CONSOLE"
+ echo > "$CONSOLE"
+ exec sh
+}
+
+log() {
+ echo "rorootfs-overlay: $1" > "$CONSOLE"
+}
+
+resolve_device() {
+ local dev=$1
+
+ if [ "$(echo $dev | cut -c1-5)" = "UUID=" ]; then
+ local uuid=$(echo $dev | cut -c6-)
+ new_dev="/dev/disk/by-uuid/$uuid"
+ elif [ "$(echo $dev | cut -c1-9)" = "PARTUUID=" ]; then
+ local partuuid=$(echo $dev | cut -c10-)
+ new_dev="/dev/disk/by-partuuid/$partuuid"
+ elif [ "$(echo $dev | cut -c1-10)" = "PARTLABEL=" ]; then
+ local partlabel=$(echo $dev | cut -c11-)
+ new_dev="/dev/disk/by-partlabel/$partlabel"
+ elif [ "$(echo $dev | cut -c1-6)" = "LABEL=" ]; then
+ local label=$(echo $dev | cut -c7-)
+ new_dev="/dev/disk/by-label/$label"
+ else
+ new_dev="$dev"
+ fi
+
+ if [ "$new_dev" != "$dev" ] && [ ! -d /dev/disk ]; then
+ fatal "$dev device naming is not supported without udev"
+ fi
+
+ echo "$new_dev"
+}
+
+wait_for_device() {
+ local dev=$1
+
+ # Skip for e.g. `rootrw=ubi0:overlay`
+ echo "$dev" | grep -q ":" && return
+
+ counter=0
+ while [ ! -b "$dev" ]; do
+ sleep .100
+ counter=$((counter + 1))
+ if [ $counter -ge 50 ]; then
+ fatal "$dev is not availble"
+ exit
+ fi
+ done
+}
+
+early_setup
+
+[ -z "${CONSOLE+x}" ] && CONSOLE="/dev/console"
+
+read_args
+
+mount_and_boot() {
+ mkdir -p $ROOT_MOUNT $ROOT_ROMOUNT $ROOT_RWMOUNT
+
+ # Build mount options for read only root file system.
+ # If no read-only device was specified via kernel command line, use
+ # current root file system via bind mount.
+ ROOT_RODEVICE=$(resolve_device "$ROOT_RODEVICE")
+ wait_for_device "${ROOT_RODEVICE}"
+ ROOT_ROMOUNTPARAMS_BIND="-o ${ROOT_ROMOUNTOPTIONS} /"
+ if [ -n "${ROOT_RODEVICE}" ]; then
+ ROOT_ROMOUNTPARAMS="-o ${ROOT_ROMOUNTOPTIONS_DEVICE} $ROOT_RODEVICE"
+ if [ -n "${ROOT_ROFSTYPE}" ]; then
+ ROOT_ROMOUNTPARAMS="-t $ROOT_ROFSTYPE $ROOT_ROMOUNTPARAMS"
+ fi
+ else
+ ROOT_ROMOUNTPARAMS="$ROOT_ROMOUNTPARAMS_BIND"
+ fi
+
+ # Mount root file system to new mount-point, if unsuccessful, try bind
+ # mounting current root file system.
+ # shellcheck disable=SC2086
+ if ! $MOUNT $ROOT_ROMOUNTPARAMS "$ROOT_ROMOUNT" 2>/dev/null; then
+ log "Could not mount $ROOT_RODEVICE, bind mounting..."
+ if ! $MOUNT $ROOT_ROMOUNTPARAMS_BIND "$ROOT_ROMOUNT"; then
+ fatal "Could not mount read-only rootfs"
+ fi
+ fi
+
+ # Remounting root file system as read only.
+ if ! $MOUNT -o remount,ro "$ROOT_ROMOUNT"; then
+ fatal "Could not remount read-only rootfs as read only"
+ fi
+
+ # If future init is the same as current file, use $ROOT_ROINIT
+ # Tries to avoid loop to infinity if init is set to current file via
+ # kernel command line
+ if cmp -s "$0" "$INIT"; then
+ INIT="$ROOT_ROINIT"
+ fi
+
+ # Build mount options for read write root file system.
+ # If a read-write device was specified via kernel command line, use
+ # it, otherwise default to tmpfs.
+ if [ -n "${ROOT_RWDEVICE}" ]; then
+ ROOT_RWDEVICE=$(resolve_device "$ROOT_RWDEVICE")
+ wait_for_device "${ROOT_RWDEVICE}"
+ ROOT_RWMOUNTPARAMS="-o $ROOT_RWMOUNTOPTIONS_DEVICE $ROOT_RWDEVICE"
+ if [ -n "${ROOT_RWFSTYPE}" ]; then
+ ROOT_RWMOUNTPARAMS="-t $ROOT_RWFSTYPE $ROOT_RWMOUNTPARAMS"
+ fi
+ else
+ ROOT_RWMOUNTPARAMS="-t tmpfs -o $ROOT_RWMOUNTOPTIONS"
+ fi
+
+ # Mount read-write file system into initram root file system
+ # shellcheck disable=SC2086
+ if ! $MOUNT $ROOT_RWMOUNTPARAMS $ROOT_RWMOUNT; then
+ fatal "Could not mount read-write rootfs"
+ fi
+
+ # Reset read-write file system if specified
+ if [ "yes" = "$ROOT_RWRESET" ] && [ -n "${ROOT_RWMOUNT}" ]; then
+ rm -rf ${ROOT_RWMOUNT:?}/*
+ fi
+
+ # Determine which unification file system to use
+ union_fs_type=""
+ if grep -w "overlay" /proc/filesystems >/dev/null; then
+ union_fs_type="overlay"
+ elif grep -w "aufs" /proc/filesystems >/dev/null; then
+ union_fs_type="aufs"
+ else
+ union_fs_type=""
+ fi
+
+ # Create/Mount overlay root file system
+ case $union_fs_type in
+ "overlay")
+ mkdir -p $ROOT_RWMOUNT/upperdir $ROOT_RWMOUNT/work
+ $MOUNT -t overlay overlay \
+ -o "$(printf "%s%s%s" \
+ "lowerdir=$ROOT_ROMOUNT," \
+ "upperdir=$ROOT_RWMOUNT/upperdir," \
+ "workdir=$ROOT_RWMOUNT/work")" \
+ $ROOT_MOUNT
+ ;;
+ "aufs")
+ $MOUNT -t aufs i\
+ -o "dirs=$ROOT_RWMOUNT=rw:$ROOT_ROMOUNT=ro" \
+ aufs $ROOT_MOUNT
+ ;;
+ "")
+ fatal "No overlay filesystem type available"
+ ;;
+ esac
+
+ # Execute any preinit scripts
+ if [ -x "${PREINIT}" ]; then
+ ${PREINIT}
+ fi
+
+ # Move read-only and read-write root file system into the overlay
+ # file system
+ mkdir -p $ROOT_MOUNT/$ROOT_ROMOUNT $ROOT_MOUNT/$ROOT_RWMOUNT
+ $MOUNT -n --move $ROOT_ROMOUNT ${ROOT_MOUNT}/$ROOT_ROMOUNT
+ $MOUNT -n --move $ROOT_RWMOUNT ${ROOT_MOUNT}/$ROOT_RWMOUNT
+
+ $MOUNT -n --move /proc ${ROOT_MOUNT}/proc
+ $MOUNT -n --move /sys ${ROOT_MOUNT}/sys
+ $MOUNT -n --move /dev ${ROOT_MOUNT}/dev
+
+
+ cd $ROOT_MOUNT
+
+ # switch to actual init in the overlay root file system
+ exec switch_root $ROOT_MOUNT "$INIT" ||
+ fatal "Couldn't chroot, dropping to shell"
+}
+
+mount_and_boot
diff --git a/buildroot-external/dracut/modules.d/99readonly-rootfs-overlay/module-setup.sh b/buildroot-external/dracut/modules.d/99readonly-rootfs-overlay/module-setup.sh
new file mode 100644
index 00000000..1c8bba54
--- /dev/null
+++ b/buildroot-external/dracut/modules.d/99readonly-rootfs-overlay/module-setup.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+
+check() {
+ require_binaries busybox || return 1
+ require_binaries cat || return 1
+ require_binaries switch_root || return 1
+ require_binaries cmp || return 1
+ require_binaries expr || return 1
+ require_binaries grep || return 1
+ require_binaries mkdir || return 1
+ require_binaries mount || return 1
+ require_binaries modprobe || return 1
+ require_binaries log || return 1
+ return 0
+}
+
+depends() {
+ return 0
+}
+
+installkernel() {
+ return 0
+}
+
+install_busybox_links() {
+ dir="${1}"
+ linkname="${2}"
+
+ (cd "${dracutsysrootdir?}${dir}" &&
+ for x in *; do
+ if [ "$(readlink "${x}")" = "${linkname}" ]; then
+ ln -sf "${linkname}" "${initdir?}/${dir}/${x}"
+ fi
+ done
+ )
+}
+
+install() {
+
+ inst_multiple mount umount cat cmp grep mkdir expr chroot
+
+ # Install busybox binary
+ inst_multiple /bin/busybox
+ if [ -e "${dracutsysrootdir?}/lib64" ]; then
+ ln -sf lib "${initdir?}/lib64"
+ ln -sf lib "${initdir?}/usr/lib64"
+ fi
+
+ if [ -e "${dracutsysrootdir?}/lib32" ]; then
+ ln -sf lib "${initdir?}/lib32"
+ ln -sf lib "${initdir?}/usr/lib32"
+ fi
+
+ install_busybox_links "/bin" "busybox"
+ install_busybox_links "/sbin" "../bin/busybox"
+ if [ ! -L "${dracutsysrootdir?}/bin" ]; then
+ install_busybox_links "/usr/bin" "../../bin/busybox"
+ install_busybox_links "/usr/sbin" "../../bin/busybox"
+ fi
+
+ # inst does not work for some reason. Use cp(1) instead.
+ #inst "$moddir/init-readonly-rootfs-overlay-boot.sh" "/init"
+ cp $moddir/init-readonly-rootfs-overlay-boot.sh $initdir/init
+}