From a97dea93d28ba272613029e46a8a0b1f699729d8 Mon Sep 17 00:00:00 2001 From: Richard Maw Date: Tue, 27 May 2014 14:58:14 +0000 Subject: Add initial version of initramfs script --- init | 107 ++++++++++++++++++++++++++++++++++++++++++++++++ initramfs-scripts.morph | 5 +++ 2 files changed, 112 insertions(+) create mode 100644 init create mode 100644 initramfs-scripts.morph diff --git a/init b/init new file mode 100644 index 00000000..fa31c0e7 --- /dev/null +++ b/init @@ -0,0 +1,107 @@ +#!/bin/sh +set -e + +# We need proc for reading the kernel command line +mount -n -t proc none /proc + +set -- $(cat /proc/cmdline) + +# We don't want to leave mount points around +umount /proc + +for arg; do + case "$arg" in + root=LABEL=*) + if [ x"$root_type" != x ]; then + echo "Warning, multiple root= specified, using latest." + fi + root_type=label + root="${arg#root=LABEL=}" + ;; + root=UUID=*) + if [ x"$root_type" != x ]; then + echo "Warning, multiple root= specified, using latest." + fi + root_type=uuid + root="${arg#root=UUID=}" + ;; + root=*) + if [ x"$root_type" != x ]; then + echo "Warning, multiple root= specified, using latest." + fi + root_type=disk + root="${arg#root=}" + ;; + rootflags=*) + if [ x"$rootflags" != x ]; then + echo "Warning, multiple rootflags= specified, using latest." + fi + rootflags=",${arg#rootflags=}" + ;; + rootfstype=*) + if [ x"$rootflags" != x ]; then + echo "Warning, multiple rootfstype= specified, using latest." + fi + rootfstype="${arg#rootfstype=}" + ;; + rootdelay=*) + if [ x"$rootflags" != x ]; then + echo "Warning, multiple rootdelay= specified, using latest." + fi + rootfstype="${arg#rootdelay=}" + ;; + ro) + ro=ro + ;; + rw) + ro=rw + ;; + init=*) + init="${arg#init=}" + ;; + esac +done + +if [ x"$rootdelay" != x ]; then + sleep "$rootdelay" +fi + +if [ x"$rootfstype" = x ]; then + # Warn that busybox may not be able to auto-detect rootfs type + cat <<\EOF +Warning, rootfs type not specified, auto-detection of type is slow and +may fail. Please add rootfstype=$type to kernel command line. +EOF +fi + +mount -n -t devtmpfs devtmpfs /dev +case "$root_type" in +disk) + mount -n -t "${rootfstype}" -o "${ro-rw}""$rootflags" "$root" /mnt + ;; +label) + disk="$(findfs LABEL="$root")" + if [ x"$disk" = x ]; then + echo disk with label $root not found + blkid + exit 1 + fi + mount -n -t "${rootfstype}" -o "${ro-rw}""$rootflags" "$disk" /mnt + ;; +uuid) + disk="$(findfs UUID="$root")" + if [ x"$disk" = x ]; then + echo disk with UUID $root not found + blkid + exit 1 + fi + mount -n -t "${rootfstype}" -o "${ro-rw}""$rootflags" "$disk" /mnt + ;; +'') + echo "Error, no root specified" + exit 1 + ;; +esac +umount -n /dev + +exec switch_root -c /dev/console /mnt "${init-/sbin/init}" diff --git a/initramfs-scripts.morph b/initramfs-scripts.morph new file mode 100644 index 00000000..77bba209 --- /dev/null +++ b/initramfs-scripts.morph @@ -0,0 +1,5 @@ +name: initramfs-scripts +kind: chunk +build-system: manual +install-commands: +- install -m 755 init "$DESTDIR/init" -- cgit v1.2.1 From a3ddeed683d765f5c7638c23ca3b95a9914a37b6 Mon Sep 17 00:00:00 2001 From: Richard Maw Date: Thu, 26 Mar 2015 14:06:18 +0000 Subject: Drop into /bin/sh on failure Change-Id: Iff3f7d911088842d430e7946f7a1d4cb6edbfa93 --- init | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/init b/init index fa31c0e7..80bee3cf 100644 --- a/init +++ b/init @@ -1,5 +1,5 @@ #!/bin/sh -set -e +trap 'exec /bin/sh' INT EXIT # We need proc for reading the kernel command line mount -n -t proc none /proc -- cgit v1.2.1 From 062c5d3aece2e308aa7fc03acab1b3b6dd4270b2 Mon Sep 17 00:00:00 2001 From: Richard Maw Date: Thu, 26 Mar 2015 14:06:30 +0000 Subject: Support rootwait (enabled by default) Change-Id: Ie1cb0c136cb9bc2873d86bbc244dcacdcf85b65d --- init | 68 +++++++++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 43 insertions(+), 25 deletions(-) diff --git a/init b/init index 80bee3cf..65bf6e87 100644 --- a/init +++ b/init @@ -9,6 +9,7 @@ set -- $(cat /proc/cmdline) # We don't want to leave mount points around umount /proc +rootwait=true # defaults to off in the kernel, I think it's more useful on for arg; do case "$arg" in root=LABEL=*) @@ -50,6 +51,12 @@ for arg; do fi rootfstype="${arg#rootdelay=}" ;; + rootwait) + rootwait=true + ;; + norootwait) + rootwait=false + ;; ro) ro=ro ;; @@ -75,33 +82,44 @@ EOF fi mount -n -t devtmpfs devtmpfs /dev -case "$root_type" in -disk) - mount -n -t "${rootfstype}" -o "${ro-rw}""$rootflags" "$root" /mnt - ;; -label) - disk="$(findfs LABEL="$root")" - if [ x"$disk" = x ]; then - echo disk with label $root not found - blkid - exit 1 - fi - mount -n -t "${rootfstype}" -o "${ro-rw}""$rootflags" "$disk" /mnt - ;; -uuid) - disk="$(findfs UUID="$root")" - if [ x"$disk" = x ]; then - echo disk with UUID $root not found - blkid +while true; do + case "$root_type" in + disk) + if mount -n -t "${rootfstype}" -o "${ro-rw}""$rootflags" "$root" /mnt; then + break + else + echo disk $root not found + blkid + fi + ;; + label) + disk="$(findfs LABEL="$root")" + if [ x"$disk" = x ]; then + echo disk with label $root not found + blkid + else + mount -n -t "${rootfstype}" -o "${ro-rw}""$rootflags" "$disk" /mnt && break + fi + ;; + uuid) + disk="$(findfs UUID="$root")" + if [ x"$disk" = x ]; then + echo disk with UUID $root not found + blkid + else + mount -n -t "${rootfstype}" -o "${ro-rw}""$rootflags" "$disk" /mnt && break + fi + ;; + '') + echo "Error, no root specified" exit 1 + ;; + esac + if "$rootwait"; then + echo Trying again in 0.5 seconds + sleep 0.5 fi - mount -n -t "${rootfstype}" -o "${ro-rw}""$rootflags" "$disk" /mnt - ;; -'') - echo "Error, no root specified" - exit 1 - ;; -esac +done umount -n /dev exec switch_root -c /dev/console /mnt "${init-/sbin/init}" -- cgit v1.2.1 From a16968232cbcffdf901650ac260689a1f3664dfe Mon Sep 17 00:00:00 2001 From: Richard Maw Date: Tue, 19 May 2015 09:50:34 +0000 Subject: Convert build-system to autotools-like This removes the need for an embedded morphology in the repository. Change-Id: I0ceff8f9b12458f7a4d0d5af10a6eba32fb44041 --- Makefile | 9 +++++++++ configure | 1 + initramfs-scripts.morph | 5 ----- 3 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 Makefile create mode 100755 configure delete mode 100644 initramfs-scripts.morph diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..e00cf308 --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ + +SCRIPTS = init + +all: + +install: $(SCRIPTS) + for script in $^ ; do\ + install -D -m 755 "$$script" $(DESTDIR)/"$$script"; \ + done diff --git a/configure b/configure new file mode 100755 index 00000000..1a248525 --- /dev/null +++ b/configure @@ -0,0 +1 @@ +#!/bin/sh diff --git a/initramfs-scripts.morph b/initramfs-scripts.morph deleted file mode 100644 index 77bba209..00000000 --- a/initramfs-scripts.morph +++ /dev/null @@ -1,5 +0,0 @@ -name: initramfs-scripts -kind: chunk -build-system: manual -install-commands: -- install -m 755 init "$DESTDIR/init" -- cgit v1.2.1 From e5c71f0ca075bd29ffd55ec0c25804585bc21046 Mon Sep 17 00:00:00 2001 From: Richard Maw Date: Tue, 19 May 2015 09:52:28 +0000 Subject: Add systemd shutdownramfs support Systemd will, if there exists a /run/initramfs/shutdown executable, pivot into /run/initramfs and exec /shutdown when shutting down. This allows / to be unmounted, rather than just remounting read-only and hoping for the best. Change-Id: If42fc21380f74e039b02d9ef9b0491c24276f098 --- Makefile | 2 +- shutdown | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 shutdown diff --git a/Makefile b/Makefile index e00cf308..97ad4751 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -SCRIPTS = init +SCRIPTS = init shutdown all: diff --git a/shutdown b/shutdown new file mode 100644 index 00000000..09281dd3 --- /dev/null +++ b/shutdown @@ -0,0 +1,66 @@ +#!/bin/sh + +fail(){ + echo "$@" >&2 + # The behaviour on failure of systemd when shutting down without a + # shutdownramfs is to freeze if it fails, but the behaviour of an initramfs + # on failure is to drop you into a recovery shell. The latter seems more + # useful. + exec /bin/sh +} + +startswith(){ + # Filter out lines that don't start with $1 + # grep ^EXPR is usually sufficient, but would require escaping of EXPR. + # Instead this compares the line to the line with its prefix stripped, + # so if the line is different, then it started with that prefix. + # It's ugly, but is less logic than escaping the regular expression and + # using grep, more reliable than not making any effort to escape, and + # less surprising than requiring the parameter to be pre-escaped. + while read -r line; do + if [ "${line#"$1"}" != "$line" ]; then + printf '%s\n' "$line" + fi + done +} + +recursive_umount(){ + # Recursively unmount every mountpoint under $1. + # This works by filtering to select mountpoints from mountinfo that start + # with the absolute path of the directory given. + # It unmounts in reverse-order, so that it may unmount dependent mounts + # first, and it has to handle the paths having octal escape sequences. + set -- "$(readlink -f "$1")" + cut -d' ' -f5 /proc/self/mountinfo | startswith "$1" \ + | sort -r | while read -r mp; do + umount "$(echo -e "$mp")" + done +} + +# Give the rootfs another chance to write its state to disk. +sync + +# Kill any http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons/ +# as we don't have any facility to cleanly shut them down in this initramfs. +killall5 + +# Recursively unmount the old root, so they have a chance of performing +# unmount-time cleanup. +recursive_umount /oldroot + +case "$1" in +reboot|poweroff|halt) + if ! "$1" -f; then + fail "$1 command failed" + fi + ;; +kexec) + # probably don't have this, but we'll try anyway + if ! kexec -e; then + fail "$1 command failed" + fi + ;; +*) + fail "Unrecognized shutdown verb $1" + ;; +esac -- cgit v1.2.1