diff options
Diffstat (limited to '')
-rw-r--r-- | scripts/functions | 581 | ||||
-rwxr-xr-x | scripts/init-top/all_generic_ide | 28 | ||||
-rwxr-xr-x | scripts/init-top/blacklist | 25 | ||||
-rwxr-xr-x | scripts/init-top/keymap | 18 | ||||
-rw-r--r-- | scripts/local | 223 | ||||
-rwxr-xr-x | scripts/local-premount/resume | 46 | ||||
-rw-r--r-- | scripts/nfs | 166 |
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 +} |