slackware-current/source/a/mkinitrd/init
Patrick J Volkerding 62d2eb317f Sun Nov 24 23:09:54 UTC 2024
a/mkinitrd-1.4.11-x86_64-49.txz:  Rebuilt.
  setup.01.mkinitrd: removed KERNEL_SYMLINK option.
  If a kernel is provided to geninitrd on the command line ($1), this will
  always be the kernel used.
  Thanks to Mechanikx.
  Removed GENINITRD_SILENT option.
  init: cap the size of /run to 25% of the system RAM since the previous
  default of 32M is way too small for many purposes. I have seen other Linux
  systems cap this at half the system RAM, but that seems to me a bit much.
  /etc/default/geninitrd:
  Added GENINITRD_OVERRIDE_SCRIPT which can be set to anything you like.
  Support for hardcoded {/usr/local/sbin,/opt/sbin}/geninitrd was removed.
  Added GENINITRD_DIALOG (do we want the dialog --infobox output?)
  Added GENINITRD_COMMAND_OUTPUT (do we want to see command output?)
a/sysvinit-scripts-15.1-noarch-23.txz:  Rebuilt.
  rc.S: cap the size of /run to 25% of the system RAM.
l/gtk4-4.16.7-x86_64-1.txz:  Upgraded.
l/vte-0.78.2-x86_64-2.txz:  Rebuilt.
n/traceroute-2.1.6-x86_64-1.txz:  Upgraded.
xfce/xfce4-xkb-plugin-0.8.3-x86_64-1.txz:  Added.
  Thanks to vladimir_vist for the suggestion,
  and Robby Workman for the build script.
2024-11-25 00:29:25 +01:00

373 lines
13 KiB
Bash

#!/bin/ash
#
# /init: init script to load kernel modules from an initramfs
# This requires that your kernel supports initramfs!!!
#
# Copyright 2004 Slackware Linux, Inc., Concord, CA, USA
# Copyright 2007, 2008, 2009, 2010, 2012 Patrick J. Volkerding, Sebeka, MN, USA
# All rights reserved.
#
# Redistribution and use of this script, with or without modification, is
# permitted provided that the following conditions are met:
#
# 1. Redistributions of this script must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
##################################################################################
# With a generic kernel, you need to load the modules needed to mount the
# root partition. This might mean a SCSI, RAID, or other drive controller
# module, as well as the module to support the root filesystem. Once the
# root partition is mounted all the other modules will be available so you
# don't need to load them here.
#
# Config files used by this script:
#
# /rootdev Contains the name of the root device, such as: /dev/hda1
#
# /rootfs Contains the root filesystem type, such as: xfs
#
# /initrd-name Contains the name of the initrd file.
#
# /resumedev Contains the name of the device to resume from hibernation.
#
# /luksdev Contains colon separated list of luks encrypted devices to
# be unlocked.
#
# /lukstrim Contains colon separated list of luks encrypted devices to
# pass '--allow-discards' when unlocking
#
# /lukskey Contains the path to a LUKS key-file for automatic unlock
# Format: LABEL=<partition_label>:/path/to/file
# UUID=<partition_uuid>:/path/to/file
#
# /wait-for-root Contains a number - the init script will wait this amount
# of seconds before creating device nodes.
#
# /keymap Contains the name for a custom keyboard map
#
# Optional:
#
# /load_kernel_modules
# A script that uses modprobe to load the desired modules.
#
# There's an example in here. To actually use it, you'll
# need to make it executable:
#
# chmod 755 load_kernel_modules
##################################################################################
# Changelog
# 10-Dec-2012 <mozes@slackware.com>
# * Added support for the official Kernel parameters to select root filesystem
# type ('rootfstype') and pause before attempting to mount the root filesystem
# ('rootdelay'). The original parameters may continue to be used.
##################################################################################
INITRD=$(cat /initrd-name)
ROOTDEV=$(cat /rootdev)
ROOTFS=$(cat /rootfs)
LUKSDEV=$(cat /luksdev)
LUKSTRIM=$(cat /lukstrim 2>/dev/null)
LUKSKEY=$(cat /lukskey)
RESUMEDEV=$(cat /resumedev)
WAIT=$(cat /wait-for-root)
KEYMAP=$(cat /keymap)
INIT=/sbin/init
PATH="/sbin:/bin:/usr/sbin:/usr/bin"
# Mount /proc and /sys:
mount -n proc /proc -t proc
mount -n sysfs /sys -t sysfs
# Other Linux systems seem to cap the size of /run to half the system memory.
# We'll go with 25% which should be much larger than the previous default of
# 32M :-)
RUNSIZE="$(expr $(grep MemTotal: /proc/meminfo | rev | cut -f 2 -d ' ' | rev) / 1024 / 4)M"
mount -n tmpfs /run -t tmpfs -o mode=0755,size=$RUNSIZE,nodev,nosuid,noexec
unset RUNSIZE
if grep devtmpfs /proc/filesystems 1>/dev/null 2>/dev/null ; then
DEVTMPFS=1
mount -n devtmpfs /dev -t devtmpfs -o size=8M
fi
# Parse command line
for ARG in $(cat /proc/cmdline); do
case $ARG in
0|1|2|3|4|5|6|S|s|single)
RUNLEVEL=$ARG
;;
init=*)
INIT=$(echo $ARG | cut -f2 -d=)
;;
luksdev=/dev/*)
LUKSDEV=$(echo $ARG | cut -f2 -d=)
;;
lukskey=*)
LUKSKEY=$(echo $ARG | cut -f2- -d=)
;;
rescue)
RESCUE=1
;;
resume=*)
RESUMEDEV=$(echo $ARG | cut -f2- -d=)
;;
root=/dev/*)
ROOTDEV=$(echo $ARG | cut -f2 -d=)
;;
root=LABEL=*)
ROOTDEV=$(echo $ARG | cut -f2- -d=)
;;
root=UUID=*)
ROOTDEV=$(echo $ARG | cut -f2- -d=)
;;
rootfs=*|rootfstype=*)
ROOTFS=$(echo $ARG | cut -f2 -d=)
;;
rootflags=*)
ROOTFLAGS=$(echo $ARG | cut -f2- -d=)
;;
waitforroot=*|rootdelay=*)
WAIT=$(echo $ARG | cut -f2 -d=)
;;
esac
done
# If udevd is available, use it to generate block devices
# else use mdev to read sysfs and generate the needed devices
if [ -x /sbin/udevd -a -x /sbin/udevadm ]; then
/sbin/udevd --daemon --resolve-names=never
/sbin/udevadm trigger --subsystem-match=block --action=add
/sbin/udevadm settle --timeout=10
else
[ "$DEVTMPFS" != "1" ] && mdev -s
fi
# Load kernel modules (ideally this was already done by udev):
if [ ! -d /lib/modules/$(uname -r) ]; then
echo "No kernel modules found for Linux $(uname -r)."
elif [ -x ./load_kernel_modules ]; then # use load_kernel_modules script:
echo "${INITRD}: Loading kernel modules from initrd image:"
. ./load_kernel_modules
else # load modules (if any) in order:
if ls /lib/modules/$(uname -r)/*.*o 1> /dev/null 2> /dev/null ; then
echo "${INITRD}: Loading kernel modules from initrd image:"
for module in /lib/modules/$(uname -r)/*.*o ; do
/sbin/modprobe $module
done
unset module
fi
fi
# Sometimes the devices need extra time to be available.
# A root filesystem on USB is a good example of that.
sleep $WAIT
# Load a custom keyboard mapping:
if [ -n "$KEYMAP" ]; then
echo "${INITRD}: Loading '$KEYMAP' keyboard mapping:"
tar xzOf /etc/keymaps.tar.gz ${KEYMAP}.bmap | loadkmap
fi
if [ "$RESCUE" = "" ]; then
# Initialize RAID:
if [ -x /sbin/mdadm ]; then
# If /etc/mdadm.conf is present, udev should DTRT on its own;
# If not, we'll make one and go from there:
if [ ! -r /etc/mdadm.conf ]; then
/sbin/mdadm -E -s >/etc/mdadm.conf
/sbin/mdadm -S -s
/sbin/mdadm -A -s
# This seems to make the kernel see partitions more reliably:
fdisk -l /dev/md* 1> /dev/null 2> /dev/null
fi
fi
# Unlock any encrypted partitions necessary to access the
# root filesystem, such as encrypted LVM Physical volumes, disk
# partitions or mdadm arrays.
# Unavailable devices such as LVM Logical Volumes will need to be
# deferred until they become available after the vgscan.
if [ -x /sbin/cryptsetup ]; then
# Determine if we have to use a LUKS keyfile:
if [ ! -z "$LUKSKEY" ]; then
mkdir /mountkey
KEYPART=$(echo $LUKSKEY |cut -f1 -d:)
KEYNAME=$(echo $KEYPART |cut -f2 -d=)
LUKSPATH="/mountkey$(echo $LUKSKEY |cut -f2 -d:)"
# Catch possible mount failure:
if blkid |grep "TYPE=\"vfat\"" |grep $KEYNAME 1>/dev/null 2>&1 ; then
MOUNTOPTS="-t vfat -o shortname=mixed"
else
MOUNTOPTS="-t auto"
fi
mount $MOUNTOPTS $(findfs $KEYPART) /mountkey 2>/dev/null
# Check if we can actually use this file:
if [ ! -f $LUKSPATH ]; then
LUKSKEY=""
else
echo ">>> Using LUKS key file: '$LUKSKEY'"
LUKSKEY="-d $LUKSPATH"
fi
fi
LUKSLIST_DEFERRED=""
LUKSLIST=$(echo $LUKSDEV | tr -s ':' ' ')
for LUKSDEV in $LUKSLIST ; do
if echo $LUKSDEV | grep -q "LABEL=" || echo $LUKSDEV | grep -q "UUID=" ; then
LUKSDEV=$(findfs $LUKSDEV)
fi
if /sbin/cryptsetup isLuks ${LUKSDEV} 1>/dev/null 2>/dev/null ; then
if echo $ROOTDEV | grep -q "LABEL=" || echo $ROOTDEV | grep -q "UUID=" ; then
CRYPTDEV="luks$(basename $LUKSDEV)"
elif [ "x$ROOTDEV" = "x$(basename $ROOTDEV)" ]; then
CRYPTDEV="$ROOTDEV"
else
CRYPTDEV="luks$(basename $LUKSDEV)"
fi
if echo $LUKSTRIM | grep -wq $LUKSDEV 2>/dev/null ; then
LUKSOPTS="--allow-discards"
else
LUKSOPTS=""
fi
if [ -z "${LUKSOPTS}" ]; then
echo "Unlocking LUKS encrypted device '${LUKSDEV}' as luks mapped device '$CRYPTDEV':"
else
echo "Unlocking LUKS encrypted device '${LUKSDEV}' as luks mapped device '$CRYPTDEV' with '$LUKSOPTS':"
fi
/sbin/cryptsetup ${LUKSOPTS} ${LUKSKEY} luksOpen ${LUKSDEV} ${CRYPTDEV} </dev/tty0 >/dev/tty0 2>&1
if [ "$ROOTDEV" = "$LUKSDEV" -o "$ROOTDEV" = "$CRYPTDEV" ] ; then
ROOTDEV="/dev/mapper/$CRYPTDEV"
fi
else
LUKSLIST_DEFERRED="${LUKSLIST_DEFERRED} ${LUKSDEV}"
fi
done
fi
# Initialize LVM:
if [ -x /sbin/vgchange ]; then
mkdir -p /var/lock/lvm # this avoids useless warnings
/sbin/vgchange -ay --ignorelockingfailure 2>/dev/null
/sbin/udevadm settle --timeout=10
fi
# Unlock any LUKS encrypted devices that were deferred above but have now
# become available due to the vgscan (i.e. filesystems on LVM Logical Volumes)
if [ -x /sbin/cryptsetup -a -n "${LUKSLIST_DEFERRED}" ]; then
for LUKSDEV in ${LUKSLIST_DEFERRED} ; do
if /sbin/cryptsetup isLuks ${LUKSDEV} 1>/dev/null 2>/dev/null ; then
if echo $ROOTDEV | grep -q "LABEL=" || echo $ROOTDEV | grep -q "UUID=" ; then
CRYPTDEV="luks$(basename $LUKSDEV)"
elif [ "x$ROOTDEV" = "x$(basename $ROOTDEV)" ]; then
CRYPTDEV="$ROOTDEV"
else
CRYPTDEV="luks$(basename $LUKSDEV)"
fi
echo "Unlocking LUKS encrypted device '${LUKSDEV}' as luks mapped device '$CRYPTDEV':"
/sbin/cryptsetup ${LUKSKEY} luksOpen ${LUKSDEV} ${CRYPTDEV} </dev/tty0 >/dev/tty0 2>&1
if [ "$ROOTDEV" = "$LUKSDEV" -o "$ROOTDEV" = "$CRYPTDEV" ] ; then
ROOTDEV="/dev/mapper/$CRYPTDEV"
fi
else
echo "LUKS device '${LUKSDEV}' unavailable for unlocking!"
fi
done
/sbin/udevadm settle --timeout=10
fi
# Scan for btrfs multi-device filesystems:
if [ -x /sbin/btrfs ]; then
/sbin/btrfs device scan
fi
# Find root device if a label or UUID was given:
if echo $ROOTDEV | grep -q "LABEL=" || \
echo $ROOTDEV | grep -q "UUID=" ; then
ROOTDEV=$(findfs $ROOTDEV)
fi
# Clean up after LUKS unlock using a keyfile:
if grep -q mountkey /proc/mounts 2>/dev/null ; then
umount -l /mountkey
rmdir /mountkey 2>/dev/null
fi
# Resume state from swap
if [ "$RESUMEDEV" != "" ]; then
# Find resume device if a label or UUID was given:
if echo $RESUMEDEV | grep -q "LABEL=" || \
echo $RESUMEDEV | grep -q "UUID=" ; then
RESUMEDEV=$(findfs $RESUMEDEV)
elif ls -l $RESUMEDEV | grep -q "^l" ; then
RESUMEDEV=$(readlink -f $RESUMEDEV)
fi
echo "Trying to resume from $RESUMEDEV"
RESMAJMIN=$(ls -l $RESUMEDEV | tr , : | awk '{ print $5$6 }')
echo $RESMAJMIN > /sys/power/resume
fi
# Switch to real root partition:
/sbin/udevadm settle --timeout=10
echo 0x0100 > /proc/sys/kernel/real-root-dev
mount -o ro${ROOTFLAGS:+,$ROOTFLAGS} -t $ROOTFS $ROOTDEV /mnt
if [ ! -r /mnt/sbin/init ]; then
echo "ERROR: No /sbin/init found on rootdev (or not mounted). Trouble ahead."
echo " You can try to fix it. Type 'exit' when things are done."
echo
/bin/sh
fi
else
echo
echo "RESCUE mode"
echo
echo " You can try to fix or rescue your system now. If you want"
echo " to boot into your fixed system, mount your root filesystem"
echo " read-only under /mnt:"
echo
echo " # mount -o ro -t filesystem root_device /mnt"
echo
echo " Type 'exit' when things are done."
echo
/bin/sh
fi
# Mount additional filesystems
if [ -f /addfstab ]; then
while read DEV MNTPNT FS OPTS DUMP PASSNO ; do
if echo $DEV | grep -qE '(LABEL|UUID)=' ; then
DEV=$(findfs $DEV)
fi
echo $DEV "/mnt/"$MNTPNT $FS "ro,"$OPTS $DUMP $PASSNO >> /etc/fstab
done < /addfstab
mount -a
fi
# Need to make sure OPTIONS+="db_persist" exists for all dm devices
# That should be handled in /sbin/mkinitrd now
/sbin/udevadm info --cleanup-db
/sbin/udevadm control --exit
unset ERR
mount -o move /proc /mnt/proc
mount -o move /sys /mnt/sys
mount -o move /run /mnt/run
[ "$DEVTMPFS" = "1" ] && mount -o move /dev /mnt/dev
echo "${INITRD}: exiting"
exec switch_root /mnt $INIT $RUNLEVEL