summaryrefslogtreecommitdiffstats
path: root/source/a/mkinitrd/init
diff options
context:
space:
mode:
Diffstat (limited to 'source/a/mkinitrd/init')
-rwxr-xr-xsource/a/mkinitrd/init262
1 files changed, 172 insertions, 90 deletions
diff --git a/source/a/mkinitrd/init b/source/a/mkinitrd/init
index 0559932e9..a6f1091e8 100755
--- a/source/a/mkinitrd/init
+++ b/source/a/mkinitrd/init
@@ -4,7 +4,7 @@
# This requires that your kernel supports initramfs!!!
#
# Copyright 2004 Slackware Linux, Inc., Concord, CA, USA
-# Copyright 2007, 2008 Patrick J. Volkerding, Sebeka, MN, USA
+# Copyright 2007, 2008, 2009, 2010 Patrick J. Volkerding, Sebeka, MN, USA
# All rights reserved.
#
# Redistribution and use of this script, with or without modification, is
@@ -33,95 +33,131 @@
#
# Config files used by this script:
#
-# /rootdev Contains the name of the root device, such as: /dev/hda1
+# /rootdev Contains the name of the root device, such as: /dev/hda1
#
-# /rootfs Contains the root filesystem type, such as: xfs
+# /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.
+#
+# /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 insmod to load the desired
-# modules. If this file is not present, all the modules
-# in /lib/modules/`uname -r`/ will be loaded in the usual
-# sorted order. If you need to load the modules in a
-# certain order, or if the modules need extra options,
-# then use a load_kernel_modules script.
-#
-# There's an example in here. To actually use it, you'll
-# need to make it executable:
-#
-# chmod 755 load_kernel_modules
-
-INITRD=`cat /initrd-name`
-ROOTDEV=`cat /rootdev`
-ROOTFS=`cat /rootfs`
-LUKSDEV=`cat /luksdev`
-RESUMEDEV=`cat /resumedev`
-WAIT=`cat /wait-for-root`
-KEYMAP=`cat /keymap`
+#
+# /load_kernel_modules
+# A script that uses insmod to load the desired
+# modules. If this file is not present, all the modules
+# in /lib/modules/$(uname -r)/ will be loaded in the usual
+# sorted order. If you need to load the modules in a
+# certain order, or if the modules need extra options,
+# then use a load_kernel_modules script.
+#
+# There's an example in here. To actually use it, you'll
+# need to make it executable:
+#
+# chmod 755 load_kernel_modules
+
+INITRD=$(cat /initrd-name)
+ROOTDEV=$(cat /rootdev)
+ROOTFS=$(cat /rootfs)
+LUKSDEV=$(cat /luksdev)
+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
+if grep devtmpfs /proc/filesystems 1>/dev/null 2>/dev/null ; then
+ DEVTMPFS=1
+ mount -n devtmpfs /dev -t devtmpfs
+fi
+
# Parse command line
-for ARG in `cat /proc/cmdline`; do
+for ARG in $(cat /proc/cmdline); do
case $ARG in
- rescue)
- RESCUE=1
- ;;
- root=/dev/*)
- ROOTDEV=`echo $ARG | cut -f2 -d=`
+ 0|1|2|3|4|5|6|S|s|single)
+ RUNLEVEL=$ARG
;;
- rootfs=*)
- ROOTFS=`echo $ARG | cut -f2 -d=`
+ init=*)
+ INIT=$(echo $ARG | cut -f2 -d=)
;;
luksdev=/dev/*)
- LUKSDEV=`echo $ARG | cut -f2 -d=`
+ LUKSDEV=$(echo $ARG | cut -f2 -d=)
;;
- waitforroot=*)
- WAIT=`echo $ARG | cut -f2 -d=`
+ lukskey=*)
+ LUKSKEY=$(echo $ARG | cut -f2- -d=)
;;
- root=LABEL=*)
- ROOTDEV=`echo $ARG | cut -f2- -d=`
+ rescue)
+ RESCUE=1
;;
resume=*)
- RESUMEDEV=`echo $ARG | cut -f2 -d=`
+ RESUMEDEV=$(echo $ARG | cut -f2 -d=)
;;
- 0|1|2|3|4|5|6)
- RUNLEVEL=$ARG
+ 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=*)
+ ROOTFS=$(echo $ARG | cut -f2 -d=)
+ ;;
+ waitforroot=*)
+ WAIT=$(echo $ARG | cut -f2 -d=)
;;
esac
done
# Load kernel modules:
-if [ ! -d /lib/modules/`uname -r` ]; then
- echo "No kernel modules found for Linux `uname -r`."
+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
+ 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
- insmod $module
+ for module in /lib/modules/$(uname -r)/*.*o ; do
+ /sbin/insmod $module
done
unset module
fi
fi
-# Sometimes the devices needs extra time to be available.
-# root on USB are good example of that.
+# Sometimes the devices need extra time to be available.
+# A root filesystem on USB is a good example of that.
sleep $WAIT
# 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
- /sbin/udevadm trigger --subsystem-match=block
+ /sbin/udevadm control --property=STARTUP=1
+ /sbin/udevadm trigger --subsystem-match=block --action=add
/sbin/udevadm settle --timeout=10
+ /sbin/udevadm control --property=STARTUP=
else
- mdev -s
+ [ "$DEVTMPFS" != "1" ] && mdev -s
fi
# Load a custom keyboard mapping:
@@ -136,62 +172,106 @@ if [ "$RESCUE" = "" ]; then
/sbin/mdadm -E -s >/etc/mdadm.conf
/sbin/mdadm -A -s
fi
-
- # Find root device if a label was given:
- if echo $ROOTDEV | grep -q "LABEL=" ; then
- ROOTDEV=`findfs $ROOTDEV`
- fi
- # Make encrypted root partition available:
- # The useable device will be under /dev/mapper/
- # Three scenarios for the commandline exist:
- # 1- ROOTDEV is on a LUKS volume, and LUKSDEV is a real block device
- # 2- ROOTDEV is on a LVM volume, and LUKSDEV is a real block device
- # 3- ROOTDEV is on a LUKS volume, and LUKSDEV is on a LVM volume
- # Case (3) will have to wait until we initialize the LVM.
- # Test if ROOTDEV is "/dev/someting" or just "something" - the first means
- # ROOTDEV is on a LVM volume (scenario 2); we don't need to rewrite ROOTDEV.
- # The second means that ROOTDEV is on a LUKS volume (scenario 1).
- CRYPTDEV=""
+ # 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
- # If we find a LUKS device now, it is on a real block device:
- if /sbin/cryptsetup isLuks ${LUKSDEV} 1>/dev/null 2>/dev/null ; then
- CRYPTDEV=$(basename $ROOTDEV)
- echo "Unlocking LUKS crypt volume '${CRYPTDEV}' on device '$LUKSDEV':"
- /sbin/cryptsetup luksOpen ${LUKSDEV} $CRYPTDEV </dev/systty >/dev/systty 2>&1
- if [ "$CRYPTDEV" == "$ROOTDEV" ]; then # scenario 1
- ROOTDEV="/dev/mapper/${CRYPTDEV}"
+
+ # Determine if we have to use a LUKS keyfile:
+ if [ ! -z "$LUKSKEY" ]; then
+ mkdir /mountkey
+ KEYPART=$(echo $LUKSKEY |cut -f1 -d:)
+ LUKSPATH="/mountkey$(echo $LUKSKEY |cut -f2 -d:)"
+ # Catch possible mount failure:
+ if blkid -t TYPE=vfat $KEYPART 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 /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
+ LUKSLIST_DEFERRED="${LUKSLIST_DEFERRED} ${LUKSDEV}"
+ fi
+ done
fi
# Initialize LVM:
- if [ -x /sbin/vgscan ]; then
- /sbin/vgscan --mknodes --ignorelockingfailure
- sleep 10
+ if [ -x /sbin/vgchange ]; then
/sbin/vgchange -ay --ignorelockingfailure
fi
- # Make encrypted root partition available (scenario 3):
- # We have to handle cases here where the LUKS volume is created on a LV
- if [ -x /sbin/cryptsetup ]; then
- if /sbin/cryptsetup isLuks ${LUKSDEV} 1>/dev/null 2>/dev/null ; then
- # Only act if we could not open the LUKS device before (i.e. is on a LV):
- if [ "x$CRYPTDEV" == "x" ]; then
- echo "Unlocking LUKS crypt volume '${ROOTDEV}' on device '$LUKSDEV':"
- /sbin/cryptsetup luksOpen ${LUKSDEV} $ROOTDEV </dev/systty >/dev/systty 2>&1
- ROOTDEV="/dev/mapper/${ROOTDEV}"
+ # 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
- fi
+ done
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
if ls -l $RESUMEDEV | grep -q "^l" ; then
- RESUMEDEV=`ls -l $RESUMEDEV | awk '{ print $NF }'`
+ RESUMEDEV=$(ls -l $RESUMEDEV | awk '{ print $NF }')
fi
echo "Trying to resume from $RESUMEDEV"
- RESMAJMIN=`ls -l $RESUMEDEV | tr , : | awk '{ print $5$6 }'`
+ RESMAJMIN=$(ls -l $RESUMEDEV | tr , : | awk '{ print $5$6 }')
echo $RESMAJMIN > /sys/power/resume
fi
@@ -206,6 +286,7 @@ if [ "$RESCUE" = "" ]; then
/bin/sh
fi
else
+ echo
echo "RESCUE mode"
echo
echo " You can try to fix or rescue your system now. If you want"
@@ -219,12 +300,13 @@ else
/bin/sh
fi
-if ps axc | grep -q udevd ; then
- killall udevd
+if pgrep udevd >/dev/null ; then
+ pkill udevd
fi
unset ERR
-umount /proc
-umount /sys
+mount -o move /proc /mnt/proc
+mount -o move /sys /mnt/sys
+[ "$DEVTMPFS" = "1" ] && mount -o move /dev /mnt/dev
echo "${INITRD}: exiting"
-exec switch_root /mnt /sbin/init $RUNLEVEL
+exec switch_root /mnt $INIT $RUNLEVEL