summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 15:45:07 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 15:45:07 +0000
commit3b043b08c9b52424072db56be6636ff44c737e83 (patch)
treed64185acc33a046c8bb297641a16b01ec167eaa5 /scripts
parentInitial commit. (diff)
downloadinitramfs-tools-upstream.tar.xz
initramfs-tools-upstream.zip
Adding upstream version 0.142.upstream/0.142upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'scripts')
-rw-r--r--scripts/functions581
-rwxr-xr-xscripts/init-top/all_generic_ide28
-rwxr-xr-xscripts/init-top/blacklist25
-rwxr-xr-xscripts/init-top/keymap18
-rw-r--r--scripts/local223
-rwxr-xr-xscripts/local-premount/resume46
-rw-r--r--scripts/nfs166
7 files changed, 1087 insertions, 0 deletions
diff --git a/scripts/functions b/scripts/functions
new file mode 100644
index 0000000..ae11b96
--- /dev/null
+++ b/scripts/functions
@@ -0,0 +1,581 @@
+# -*- shell-script -*-
+
+_log_msg()
+{
+ if [ "${quiet?}" = "y" ]; then return; fi
+ # shellcheck disable=SC2059
+ printf "$@"
+ return 0 # Prevents error carry over in case of unavailable console
+}
+
+log_success_msg()
+{
+ _log_msg "Success: %s\\n" "$*"
+}
+
+log_failure_msg()
+{
+ _log_msg "Failure: %s\\n" "$*"
+}
+
+log_warning_msg()
+{
+ _log_msg "Warning: %s\\n" "$*"
+}
+
+log_begin_msg()
+{
+ _log_msg "Begin: %s ... " "$*"
+}
+
+log_end_msg()
+{
+ _log_msg "done.\\n"
+}
+
+panic()
+{
+ local console rest IFS
+
+ if command -v chvt >/dev/null 2>&1; then
+ chvt 1
+ fi
+
+ echo "$@"
+
+ # The panic= parameter implies we should disallow console access
+ if [ -n "${panic?}" ]; then
+ delay=
+ case "${panic?}" in
+ -*[![:digit:].]*) # invalid: wait forever
+ ;;
+ -*) # timeout < 0: reboot immediately
+ delay=0
+ ;;
+ 0 | *[![:digit:].]*) # timeout = 0 or invalid: wait forever
+ ;;
+ *) # timeout > 0: seconds before rebooting
+ delay="${panic}"
+ ;;
+ esac
+ if [ -n "${delay}" ]; then
+ echo "Rebooting automatically due to panic= boot argument"
+ sleep "${delay}"
+ reboot -f
+ else
+ echo "Halting automatically due to panic= boot argument"
+ halt -f
+ fi
+ exit # in case reboot fails, force kernel panic
+ fi
+
+ run_scripts /scripts/panic
+
+ # Try to use setsid, which will enable job control in the shell
+ # and paging in more
+ if command -v setsid >/dev/null 2>&1; then
+ unset IFS
+ read -r console rest </proc/consoles
+ if [ "${console}" = "tty0" ]; then
+ # Need to choose a specific VT
+ console="tty1"
+ fi
+ # We don't have 'setsid -c' so we need to setsid, open
+ # the tty, and finally exec an interactive shell
+ REASON="$*" PS1='(initramfs) ' setsid sh -c "exec sh -i <>/dev/${console} 1>&0 2>&1"
+ else
+ REASON="$*" PS1='(initramfs) ' sh -i </dev/console >/dev/console 2>&1
+ fi
+}
+
+maybe_break()
+{
+ case ",${break?}," in
+ *,$1,*)
+ if [ "$1" = "top" ]; then
+ # udev is not yet running, so load keyboard drivers
+ if [ "${quiet}" = "y" ]; then
+ opts="-q"
+ else
+ opts="-v"
+ fi
+ /sbin/modprobe ${opts} -a i8042 atkbd ehci-pci ehci-orion \
+ ehci-hcd ohci-hcd ohci-pci uhci-hcd usbhid xhci \
+ xhci-pci xhci-hcd
+ sleep 2
+ for modalias in /sys/bus/hid/devices/*/modalias; do
+ if [ -f "${modalias}" ]; then
+ /sbin/modprobe ${opts} -b "$(cat "${modalias}")"
+ fi
+ done
+ fi
+ panic "Spawning shell within the initramfs"
+ ;;
+ esac
+}
+
+# For boot time only; this is overridden at build time in hook-functions
+run_scripts()
+{
+ initdir=${1}
+ [ ! -d "${initdir}" ] && return
+
+ shift
+ . "${initdir}/ORDER"
+}
+
+# Load custom modules first
+load_modules()
+{
+ if [ -e /conf/modules ]; then
+ while read -r m; do
+ # Skip empty lines
+ if [ -z "$m" ]; then
+ continue
+ fi
+ # Skip comments - d?ash removes whitespace prefix
+ com=$(printf "%.1s" "${m}")
+ if [ "$com" = "#" ]; then
+ continue
+ fi
+ # shellcheck disable=SC2086
+ /sbin/modprobe $m
+ done < /conf/modules
+ fi
+}
+
+_uptime() {
+ local uptime
+ uptime="$(cat /proc/uptime)"
+ uptime="${uptime%%[. ]*}"
+ echo "$uptime"
+}
+
+time_elapsed() {
+ # shellcheck disable=SC2154
+ if [ -z "$starttime" ]; then
+ log_failure_msg "time_elapsed() called before \$starttime initialized"
+ echo 0
+ fi
+ local delta
+ delta="$(_uptime)"
+ delta=$((delta - starttime))
+ echo "$delta"
+}
+
+# lilo compatibility
+parse_numeric() {
+ case $1 in
+ *:*)
+ # Does it match /[0-9]*:[0-9]*/?
+ minor=${1#*:}
+ major=${1%:*}
+ case $major$minor in
+ *[!0-9]*)
+ # No.
+ return
+ ;;
+ esac
+ ;;
+ "" | *[!A-Fa-f0-9]*)
+ # "", "/*", etc.
+ return
+ ;;
+ *)
+ # [A-Fa-f0-9]*
+ value=$(( 0x${1} ))
+ minor=$(( (value & 0xff) | (value >> 12) & 0xfff00 ))
+ major=$(( (value >> 8) & 0xfff ))
+ ;;
+ esac
+
+ # shellcheck disable=SC2034
+ ROOT="/dev/block/${major}:${minor}"
+}
+
+# Parameter: device node to check
+# Echos fstype to stdout
+# Return value: indicates if an fs could be recognized
+get_fstype ()
+{
+ local FS FSTYPE
+ FS="${1}"
+
+ # blkid has a more complete list of file systems,
+ # but fstype is more robust
+ FSTYPE="unknown"
+ eval "$(fstype "${FS}" 2> /dev/null)"
+ if [ "$FSTYPE" = "unknown" ]; then
+ FSTYPE=$(blkid -o value -s TYPE "${FS}") || return
+ fi
+ echo "${FSTYPE}"
+ return 0
+}
+
+_set_netdev_from_ip_param()
+{
+ # If the ip= parameter is present and specifies a device, use
+ # that in preference to any device name we already have
+ local IFS=:
+ set -f
+ # shellcheck disable=SC2086
+ set -- ${IP}
+ set +f
+ if [ -n "$6" ]; then
+ DEVICE="$6"
+ return 0
+ fi
+ return 1
+}
+
+_set_netdev_from_hw_address()
+{
+ local want_address="$1"
+ local device
+ for device in /sys/class/net/*; do
+ if [ -f "$device/address" ] &&
+ [ "$(cat "$device/address")" = "$want_address" ]; then
+ DEVICE="${device##*/}"
+ return 0
+ fi
+ done
+ return 1
+}
+
+_usable_netdev_exists()
+{
+ # Look for a device with IFF_LOOPBACK clear and (IFF_BROADCAST
+ # or IFF_POINTTOPOINT) set. This is the same test the kernel
+ # and ipconfig apply to find a device.
+ local device
+ local flags
+ for device in /sys/class/net/*; do
+ if [ -f "${device}/flags" ]; then
+ flags="$(cat "${device}/flags")"
+ if [ "$((flags & 8))" -eq 0 ] &&
+ [ "$((flags & 0x12))" -ne 0 ]; then
+ return 0
+ fi
+ fi
+ done
+ return 1
+}
+
+_update_ip_param()
+{
+ # If the ip= parameter is present, and is a colon-separated list,
+ # but does not specify a device, substitute in the device name
+ # we have
+ local IFS=:
+ set -f
+ # shellcheck disable=SC2086
+ set -- ${IP}
+ set +f
+ if [ -z "$6" ] && [ $# -ge 2 ] && [ -n "${DEVICE}" ]; then
+ IP="$1:$2:$3:$4:$5:${DEVICE}"
+ shift 6 || shift $#
+ IP="${IP}:$*"
+ fi
+}
+
+configure_networking()
+{
+ local netdev_desc
+
+ # The order of precedence here is:
+ # 1. Device specified by ip= kernel parameter
+ # 2. Device matching MAC specified by BOOTIF= kernel parameter
+ # 3. Build-time DEVICE variable
+ # In case 2 we only discover the device name while waiting
+ # for a device.
+ if _set_netdev_from_ip_param; then
+ netdev_desc="${DEVICE}"
+ elif [ -n "${BOOTIF}" ]; then
+ # pxelinux sets BOOTIF to a value based on the mac address of the
+ # network card used to PXE boot
+ # pxelinux sets BOOTIF to 01-$mac_address
+
+ # strip off the leading "01-", which isn't part of the mac
+ # address
+ temp_mac=${BOOTIF#*-}
+
+ # convert to typical mac address format by replacing "-" with ":"
+ bootif_mac=""
+ IFS='-'
+ for x in $temp_mac ; do
+ if [ -z "$bootif_mac" ]; then
+ bootif_mac="$x"
+ else
+ bootif_mac="$bootif_mac:$x"
+ fi
+ done
+ unset IFS
+
+ _set_netdev_from_hw_address "${bootif_mac}"
+ netdev_desc="device with address ${bootif_mac}"
+ elif [ -n "${DEVICE}" ]; then
+ netdev_desc="${DEVICE}"
+ else
+ netdev_desc="any network device"
+ fi
+
+ # networking already configured thus bail out
+ [ -n "${DEVICE}" ] && [ -e /run/net-"${DEVICE}".conf ] && return 0
+
+ local netdevwait=180
+ log_begin_msg "Waiting up to ${netdevwait} secs for ${netdev_desc} to become available"
+ while true; do
+ if [ "$(time_elapsed)" -ge "$netdevwait" ]; then
+ log_failure_msg "Network device did not appear in time"
+ break
+ fi
+ if [ -n "${DEVICE}" ]; then
+ [ -e "/sys/class/net/${DEVICE}" ] && break
+ elif [ -n "${bootif_mac}" ]; then
+ _set_netdev_from_hw_address "${bootif_mac}" && break
+ else
+ _usable_netdev_exists && break
+ fi
+ sleep 1
+ done
+ log_end_msg
+
+ _update_ip_param
+
+ wait_for_udev 10
+
+ # support ip options see linux sources
+ # Documentation/filesystems/nfs/nfsroot.txt
+ # Documentation/frv/booting.txt
+
+ for ROUNDTTT in 2 3 4 6 9 16 25 36 64 100; do
+
+ # The NIC is to be configured if this file does not exist.
+ # Ip-Config tries to create this file and when it succeds
+ # creating the file, ipconfig is not run again.
+ for x in /run/net-"${DEVICE}".conf /run/net-*.conf ; do
+ [ -e "$x" ] && break 2
+ done
+
+ case ${IP} in
+ none|off)
+ # Do nothing
+ ;;
+ ""|on|any)
+ # Bring up device
+ ipconfig -t ${ROUNDTTT} "${DEVICE}"
+ ;;
+ dhcp|bootp|rarp|both)
+ ipconfig -t ${ROUNDTTT} -c "${IP}" -d "${DEVICE}"
+ ;;
+ *)
+ ipconfig -t ${ROUNDTTT} -d "$IP"
+ ;;
+ esac
+ done
+
+ # source ipconfig output
+ if [ -n "${DEVICE}" ]; then
+ # source specific bootdevice
+ . "/run/net-${DEVICE}.conf"
+ else
+ # source any interface...
+ # ipconfig should have quit after first response
+ . /run/net-*.conf
+ fi
+}
+
+# Wait for queued kernel/udev events
+wait_for_udev()
+{
+ command -v udevadm >/dev/null 2>&1 || return 0
+ udevadm settle ${1:+--timeout=$1}
+}
+
+# Find a specific fstab entry
+# $1=mountpoint
+# $2=fstype (optional)
+# returns 0 on success, 1 on failure (not found or no fstab)
+read_fstab_entry() {
+ # Not found by default.
+ found=1
+
+ for file in ${rootmnt?}/etc/fstab; do
+ if [ -f "$file" ]; then
+ # shellcheck disable=SC2034
+ while read -r MNT_FSNAME MNT_DIR MNT_TYPE MNT_OPTS MNT_FREQ MNT_PASS MNT_JUNK; do
+ case "$MNT_FSNAME" in
+ ""|\#*)
+ continue;
+ ;;
+ esac
+ if [ "$MNT_DIR" = "$1" ]; then
+ if [ -n "$2" ]; then
+ [ "$MNT_TYPE" = "$2" ] || continue;
+ fi
+ found=0
+ break 2
+ fi
+ done < "$file"
+ fi
+ done
+
+ return $found
+}
+
+# Resolve device node from a name. This expands any LABEL or UUID.
+# $1=name
+# Resolved name is echoed.
+resolve_device() {
+ DEV="$1"
+
+ case "$DEV" in
+ LABEL=* | UUID=* | PARTLABEL=* | PARTUUID=*)
+ DEV="$(blkid -l -t "$DEV" -o device)" || return 1
+ ;;
+ esac
+ [ -e "$DEV" ] && echo "$DEV"
+}
+
+# Check a file system.
+# $1=device
+# $2=mountpoint (for diagnostics only)
+# $3=type (may be "auto")
+_checkfs_once()
+{
+ DEV="$1"
+ NAME="$2"
+ TYPE="$3"
+ if [ "$NAME" = "/" ] ; then
+ NAME="root"
+ fi
+ FSCK_LOGFILE=/run/initramfs/fsck.log
+ FSCK_STAMPFILE=/run/initramfs/fsck-${NAME#/}
+
+ if [ "${TYPE}" = "auto" ]; then
+ TYPE="$(get_fstype "${DEV}")"
+ fi
+
+ FSCKCODE=0
+ if [ -z "${TYPE}" ]; then
+ log_warning_msg "Type of $NAME file system is unknown, so skipping check."
+ return
+ fi
+ if ! command -v fsck >/dev/null 2>&1; then
+ log_warning_msg "fsck not present, so skipping $NAME file system"
+ return
+ fi
+ if [ "${fastboot?}" = "y" ] ; then
+ log_warning_msg "Fast boot enabled, so skipping $NAME file system check."
+ return
+ fi
+
+ if [ "${forcefsck?}" = "y" ]
+ then
+ force="-f"
+ else
+ force=""
+ fi
+
+ if [ "${fsckfix?}" = "y" ]
+ then
+ fix="-y"
+ elif [ "${fsckfix?}" = "n" ]
+ then
+ fix="-n"
+ else
+ fix="-a"
+ fi
+
+ spinner=""
+ if [ -z "${debug?}" ]; then
+ spinner="-C"
+ fi
+
+ if [ "${quiet}" = n ]
+ then
+ log_begin_msg "Will now check $NAME file system"
+ # shellcheck disable=SC2086
+ logsave -a -s $FSCK_LOGFILE fsck $spinner $force $fix -V -t "$TYPE" "$DEV"
+ FSCKCODE=$?
+ log_end_msg
+ else
+ log_begin_msg "Checking $NAME file system"
+ # shellcheck disable=SC2086
+ logsave -a -s $FSCK_LOGFILE fsck $spinner $force $fix -T -t "$TYPE" "$DEV"
+ FSCKCODE=$?
+ log_end_msg
+ fi
+
+ # NOTE: "failure" is defined as exiting with a return code of
+ # 4, possibly or-ed with other flags. A return code of 1
+ # indicates that file system errors were corrected but that
+ # the boot may proceed.
+ #
+ if [ "$FSCKCODE" -eq 32 ]
+ then
+ log_warning_msg "File system check was interrupted by user"
+ elif [ $((FSCKCODE & 4)) -eq 4 ]
+ then
+ log_failure_msg "File system check of the $NAME filesystem failed"
+ return 1
+ elif [ "$FSCKCODE" -gt 1 ]
+ then
+ log_warning_msg "File system check failed but did not detect errors"
+ sleep 5
+ else
+ true > $FSCK_STAMPFILE
+ fi
+ return 0
+}
+
+checkfs()
+{
+ while ! _checkfs_once "$@"; do
+ panic "The $2 filesystem on $1 requires a manual fsck"
+ done
+}
+
+# Mount a file system. We parse the information from the fstab. This
+# should be overridden by any boot script which can mount arbitrary
+# filesystems such as /usr. This default implementation delegates to
+# local or nfs based upon the filesystem type.
+# $1=mountpoint mount location
+mountfs()
+{
+ type=local
+ read_fstab_entry "$1"
+ if [ "${MNT_TYPE}" = "nfs" ] || [ "${MNT_TYPE}" = "nfs4" ]; then
+ type=nfs
+ fi
+
+ ${type}_mount_fs "$1"
+}
+
+# Mount the root file system. It should be overridden by all
+# boot scripts.
+mountroot()
+{
+ :
+}
+
+# Run /scripts/${boot}-top. This should be overridden by all boot
+# scripts.
+mount_top()
+{
+ :
+}
+
+# Run /scripts/${boot}-premount. This should be overridden by all boot
+# scripts.
+mount_premount()
+{
+ :
+}
+
+# Run /scripts/${boot}-bottom. This should be overridden by all boot
+# scripts.
+mount_bottom()
+{
+ :
+}
diff --git a/scripts/init-top/all_generic_ide b/scripts/init-top/all_generic_ide
new file mode 100755
index 0000000..cdf69cc
--- /dev/null
+++ b/scripts/init-top/all_generic_ide
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+PREREQ=""
+prereqs()
+{
+ echo "$PREREQ"
+}
+case $1 in
+# get pre-requisites
+prereqs)
+ prereqs
+ exit 0
+ ;;
+esac
+
+# shellcheck disable=SC2013
+for x in $(cat /proc/cmdline); do
+ case ${x} in
+ all_generic_ide)
+ /sbin/modprobe ata_generic all_generic_ide=1
+ ;;
+ all_generic_ide=*)
+ if [ -n "${x#all_generic_ide=}" ]; then
+ /sbin/modprobe ata_generic all_generic_ide=1
+ fi
+ ;;
+ esac
+done
diff --git a/scripts/init-top/blacklist b/scripts/init-top/blacklist
new file mode 100755
index 0000000..d860603
--- /dev/null
+++ b/scripts/init-top/blacklist
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+PREREQ=""
+
+prereqs()
+{
+ echo "$PREREQ"
+}
+
+case $1 in
+# get pre-requisites
+prereqs)
+ prereqs
+ exit 0
+ ;;
+esac
+
+# sanity check
+[ -z "${blacklist?}" ] && exit 0
+
+# write blacklist to modprobe.d
+IFS=','
+for b in ${blacklist}; do
+ echo "blacklist $b" >> /etc/modprobe.d/initramfs.conf
+done
diff --git a/scripts/init-top/keymap b/scripts/init-top/keymap
new file mode 100755
index 0000000..1c6b2dc
--- /dev/null
+++ b/scripts/init-top/keymap
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+PREREQ=""
+prereqs()
+{
+ echo "$PREREQ"
+}
+case $1 in
+# get pre-requisites
+prereqs)
+ prereqs
+ exit 0
+ ;;
+esac
+
+if [ -x /bin/setupcon ]; then
+ /bin/setupcon
+fi
diff --git a/scripts/local b/scripts/local
new file mode 100644
index 0000000..8f9597f
--- /dev/null
+++ b/scripts/local
@@ -0,0 +1,223 @@
+# Local filesystem mounting -*- shell-script -*-
+
+local_top()
+{
+ if [ "${local_top_used}" != "yes" ]; then
+ [ "${quiet?}" != "y" ] && log_begin_msg "Running /scripts/local-top"
+ run_scripts /scripts/local-top
+ [ "$quiet" != "y" ] && log_end_msg
+ fi
+ local_top_used=yes
+}
+
+local_block()
+{
+ [ "${quiet?}" != "y" ] && log_begin_msg "Running /scripts/local-block"
+ run_scripts /scripts/local-block "$@"
+ [ "$quiet" != "y" ] && log_end_msg
+}
+
+local_premount()
+{
+ if [ "${local_premount_used}" != "yes" ]; then
+ [ "${quiet?}" != "y" ] && log_begin_msg "Running /scripts/local-premount"
+ run_scripts /scripts/local-premount
+ [ "$quiet" != "y" ] && log_end_msg
+ fi
+ local_premount_used=yes
+}
+
+local_bottom()
+{
+ if [ "${local_premount_used}" = "yes" ] || [ "${local_top_used}" = "yes" ]; then
+ [ "${quiet?}" != "y" ] && log_begin_msg "Running /scripts/local-bottom"
+ run_scripts /scripts/local-bottom
+ [ "$quiet" != "y" ] && log_end_msg
+ fi
+ local_premount_used=no
+ local_top_used=no
+}
+
+# $1=device ID to mount
+# $2=optionname (for root and etc)
+# $3=panic if device is missing (true or false, default: true)
+# Sets $DEV to the resolved device node
+local_device_setup()
+{
+ local dev_id="$1"
+ local name="$2"
+ local may_panic="${3:-true}"
+ local real_dev
+ local time_elapsed
+ local count
+
+ wait_for_udev 10
+
+ # Load ubi with the correct MTD partition and return since fstype
+ # doesn't work with a char device like ubi.
+ if [ -n "$UBIMTD" ]; then
+ /sbin/modprobe ubi "mtd=$UBIMTD"
+ DEV="${dev_id}"
+ return
+ fi
+
+ # Don't wait for a device that doesn't have a corresponding
+ # device in /dev and isn't resolvable by blkid (e.g. mtd0)
+ if [ "${dev_id#/dev}" = "${dev_id}" ] &&
+ [ "${dev_id#*=}" = "${dev_id}" ]; then
+ DEV="${dev_id}"
+ return
+ fi
+
+ # If the root device hasn't shown up yet, give it a little while
+ # to allow for asynchronous device discovery (e.g. USB). We
+ # also need to keep invoking the local-block scripts in case
+ # there are devices stacked on top of those.
+ if ! real_dev=$(resolve_device "${dev_id}") ||
+ ! get_fstype "${real_dev}" >/dev/null; then
+ log_begin_msg "Waiting for ${name}"
+
+ # Timeout is max(30, rootdelay) seconds (approximately)
+ slumber=30
+ if [ "${ROOTDELAY:-0}" -gt $slumber ]; then
+ slumber=$ROOTDELAY
+ fi
+
+ while true; do
+ sleep 1
+ time_elapsed="$(time_elapsed)"
+
+ local_block "${dev_id}"
+
+ # If mdadm's local-block script counts the
+ # number of times it is run, make sure to
+ # run it the expected number of times.
+ while true; do
+ if [ -f /run/count.mdadm.initrd ]; then
+ count="$(cat /run/count.mdadm.initrd)"
+ elif [ -n "${count}" ]; then
+ # mdadm script deleted it; put it back
+ count=$((count + 1))
+ echo "${count}" >/run/count.mdadm.initrd
+ else
+ break
+ fi
+ if [ "${count}" -ge "${time_elapsed}" ]; then
+ break;
+ fi
+ /scripts/local-block/mdadm "${dev_id}"
+ done
+
+ if real_dev=$(resolve_device "${dev_id}") &&
+ get_fstype "${real_dev}" >/dev/null; then
+ wait_for_udev 10
+ log_end_msg 0
+ break
+ fi
+ if [ "${time_elapsed}" -ge "${slumber}" ]; then
+ log_end_msg 1 || true
+ break
+ fi
+ done
+ fi
+
+ # We've given up, but we'll let the user fix matters if they can
+ while ! real_dev=$(resolve_device "${dev_id}") ||
+ ! get_fstype "${real_dev}" >/dev/null; do
+ if ! $may_panic; then
+ echo "Gave up waiting for ${name}"
+ return 1
+ fi
+ echo "Gave up waiting for ${name} device. Common problems:"
+ echo " - Boot args (cat /proc/cmdline)"
+ echo " - Check rootdelay= (did the system wait long enough?)"
+ if [ "${name}" = root ]; then
+ echo " - Check root= (did the system wait for the right device?)"
+ fi
+ echo " - Missing modules (cat /proc/modules; ls /dev)"
+ panic "ALERT! ${dev_id} does not exist. Dropping to a shell!"
+ done
+
+ DEV="${real_dev}"
+}
+
+local_mount_root()
+{
+ local_top
+ if [ -z "${ROOT}" ]; then
+ panic "No root device specified. Boot arguments must include a root= parameter."
+ fi
+ local_device_setup "${ROOT}" "root file system"
+ ROOT="${DEV}"
+
+ # Get the root filesystem type if not set
+ if [ -z "${ROOTFSTYPE}" ] || [ "${ROOTFSTYPE}" = auto ]; then
+ FSTYPE=$(get_fstype "${ROOT}")
+ else
+ FSTYPE=${ROOTFSTYPE}
+ fi
+
+ local_premount
+
+ if [ "${readonly?}" = "y" ]; then
+ roflag=-r
+ else
+ roflag=-w
+ fi
+
+ checkfs "${ROOT}" root "${FSTYPE}"
+
+ # Mount root
+ # shellcheck disable=SC2086
+ if ! mount ${roflag} ${FSTYPE:+-t "${FSTYPE}"} ${ROOTFLAGS} "${ROOT}" "${rootmnt?}"; then
+ panic "Failed to mount ${ROOT} as root file system."
+ fi
+}
+
+local_mount_fs()
+{
+ read_fstab_entry "$1"
+
+ local_device_setup "$MNT_FSNAME" "$1 file system"
+ MNT_FSNAME="${DEV}"
+
+ local_premount
+
+ if [ "${readonly}" = "y" ]; then
+ roflag=-r
+ else
+ roflag=-w
+ fi
+
+ if [ "$MNT_PASS" != 0 ]; then
+ checkfs "$MNT_FSNAME" "$MNT_DIR" "${MNT_TYPE}"
+ fi
+
+ # Mount filesystem
+ if ! mount ${roflag} -t "${MNT_TYPE}" -o "${MNT_OPTS}" "$MNT_FSNAME" "${rootmnt}${MNT_DIR}"; then
+ panic "Failed to mount ${MNT_FSNAME} as $MNT_DIR file system."
+ fi
+}
+
+mountroot()
+{
+ local_mount_root
+}
+
+mount_top()
+{
+ # Note, also called directly in case it's overridden.
+ local_top
+}
+
+mount_premount()
+{
+ # Note, also called directly in case it's overridden.
+ local_premount
+}
+
+mount_bottom()
+{
+ # Note, also called directly in case it's overridden.
+ local_bottom
+}
diff --git a/scripts/local-premount/resume b/scripts/local-premount/resume
new file mode 100755
index 0000000..63dcc49
--- /dev/null
+++ b/scripts/local-premount/resume
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+PREREQ=""
+
+prereqs()
+{
+ echo "$PREREQ"
+}
+
+case $1 in
+# get pre-requisites
+prereqs)
+ prereqs
+ exit 0
+ ;;
+esac
+
+if [ -z "${resume?}" ] || [ ! -e /sys/power/resume ]; then
+ exit 0
+fi
+
+. /scripts/functions
+. /scripts/local
+
+if ! local_device_setup "${resume}" "suspend/resume device" false; then
+ exit 0
+fi
+
+if [ "$(get_fstype "${DEV}")" = suspend ] &&
+ command -v plymouth >/dev/null &&
+ plymouth --ping; then
+ plymouth display-message --text="Resuming from hibernation"
+
+ # The above command does not wait for a framebuffer update to
+ # complete, so the kernel can freeze the framebuffer before
+ # the message is even visible. Wait just a moment to make
+ # that less likely.
+ sleep 0.1
+fi
+
+# hardcode path, uswsusp ships an resume binary too
+if [ -n "${resume_offset?}" ]; then
+ /bin/resume "${DEV}" "${resume_offset}"
+else
+ /bin/resume "${DEV}"
+fi
diff --git a/scripts/nfs b/scripts/nfs
new file mode 100644
index 0000000..26a969b
--- /dev/null
+++ b/scripts/nfs
@@ -0,0 +1,166 @@
+# NFS filesystem mounting -*- shell-script -*-
+
+# FIXME This needs error checking
+
+nfs_top()
+{
+ if [ "${nfs_top_used}" != "yes" ]; then
+ [ "${quiet?}" != "y" ] && log_begin_msg "Running /scripts/nfs-top"
+ run_scripts /scripts/nfs-top
+ [ "$quiet" != "y" ] && log_end_msg
+ fi
+ nfs_top_used=yes
+}
+
+nfs_premount()
+{
+ if [ "${nfs_premount_used}" != "yes" ]; then
+ [ "${quiet?}" != "y" ] && log_begin_msg "Running /scripts/nfs-premount"
+ run_scripts /scripts/nfs-premount
+ [ "$quiet" != "y" ] && log_end_msg
+ fi
+ nfs_premount_used=yes
+}
+
+nfs_bottom()
+{
+ if [ "${nfs_premount_used}" = "yes" ] || [ "${nfs_top_used}" = "yes" ]; then
+ [ "${quiet?}" != "y" ] && log_begin_msg "Running /scripts/nfs-bottom"
+ run_scripts /scripts/nfs-bottom
+ [ "$quiet" != "y" ] && log_end_msg
+ fi
+ nfs_premount_used=no
+ nfs_top_used=no
+}
+
+# parse nfs bootargs and mount nfs
+nfs_mount_root_impl()
+{
+ configure_networking
+
+ # get nfs root from dhcp
+ if [ "${NFSROOT}" = "auto" ]; then
+ # check if server ip is part of dhcp root-path
+ if [ "${ROOTPATH#*:}" = "${ROOTPATH}" ]; then
+ NFSROOT=${ROOTSERVER}:${ROOTPATH}
+ else
+ NFSROOT=${ROOTPATH}
+ fi
+
+ # nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>]
+ elif [ -n "${NFSROOT}" ]; then
+ # nfs options are an optional arg
+ if [ "${NFSROOT#*,}" != "${NFSROOT}" ]; then
+ NFSOPTS="-o ${NFSROOT#*,}"
+ fi
+ NFSROOT=${NFSROOT%%,*}
+ if [ "${NFSROOT#*:}" = "$NFSROOT" ]; then
+ NFSROOT=${ROOTSERVER}:${NFSROOT}
+ fi
+ fi
+
+ if [ -z "${NFSOPTS}" ]; then
+ NFSOPTS="-o retrans=10"
+ fi
+
+ nfs_premount
+
+ if [ "${readonly?}" = y ]; then
+ roflag="-o ro"
+ else
+ roflag="-o rw"
+ fi
+
+ # shellcheck disable=SC2086
+ nfsmount -o nolock ${roflag} ${NFSOPTS} "${NFSROOT}" "${rootmnt?}"
+}
+
+# NFS root mounting
+nfs_mount_root()
+{
+ nfs_top
+
+ # For DHCP
+ /sbin/modprobe af_packet
+
+ wait_for_udev 10
+
+ # Default delay is around 180s
+ delay=${ROOTDELAY:-180}
+
+ # loop until nfsmount succeeds
+ nfs_mount_root_impl
+ ret=$?
+ nfs_retry_count=0
+ while [ ${nfs_retry_count} -lt "${delay}" ] \
+ && [ $ret -ne 0 ] ; do
+ [ "$quiet" != "y" ] && log_begin_msg "Retrying nfs mount"
+ sleep 1
+ nfs_mount_root_impl
+ ret=$?
+ nfs_retry_count=$(( nfs_retry_count + 1 ))
+ [ "$quiet" != "y" ] && log_end_msg
+ done
+}
+
+nfs_mount_fs_impl()
+{
+ configure_networking
+
+ if [ -z "${NFSOPTS}" ]; then
+ NFSOPTS="-o retrans=10"
+ fi
+
+ nfs_premount
+
+ if [ "${readonly}" = y ]; then
+ roflag="-o ro"
+ else
+ roflag="-o rw"
+ fi
+
+ read_fstab_entry "$1"
+
+ # shellcheck disable=SC2086
+ nfsmount ${roflag} ${NFSOPTS} -o "${MNT_OPTS}" "$MNT_FSNAME" "${rootmnt}${MNT_DIR}"
+}
+
+nfs_mount_fs()
+{
+ nfs_top
+
+ # For DHCP
+ /sbin/modprobe af_packet
+
+ wait_for_udev 10
+
+ # Default delay is around 180s
+ delay=${ROOTDELAY:-180}
+
+ # Don't loop here; we can't sanely check if it worked like for
+ # the rootfs or /etc.
+ nfs_mount_fs_impl "$1"
+}
+
+mountroot()
+{
+ nfs_mount_root
+}
+
+mount_top()
+{
+ # Note, also called directly in case it's overridden.
+ nfs_top
+}
+
+mount_premount()
+{
+ # Note, also called directly in case it's overridden.
+ nfs_premount
+}
+
+mount_bottom()
+{
+ # Note, also called directly in case it's overridden.
+ nfs_bottom
+}