#!/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 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. # # 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` # Mount /proc and /sys: mount -n proc /proc -t proc mount -n sysfs /sys -t sysfs # Parse command line for ARG in `cat /proc/cmdline`; do case $ARG in rescue) RESCUE=1 ;; root=/dev/*) ROOTDEV=`echo $ARG | cut -f2 -d=` ;; rootfs=*) ROOTFS=`echo $ARG | cut -f2 -d=` ;; luksdev=/dev/*) LUKSDEV=`echo $ARG | cut -f2 -d=` ;; waitforroot=*) WAIT=`echo $ARG | cut -f2 -d=` ;; root=LABEL=*) ROOTDEV=`echo $ARG | cut -f2- -d=` ;; resume=*) RESUMEDEV=`echo $ARG | cut -f2 -d=` ;; 0|1|2|3|4|5|6) RUNLEVEL=$ARG ;; esac done # Load kernel modules: 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 insmod $module done unset module fi fi # Sometimes the devices needs extra time to be available. # root on USB are 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 settle --timeout=10 else mdev -s fi # 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 /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="" 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 2>&1 if [ "$CRYPTDEV" == "$ROOTDEV" ]; then # scenario 1 ROOTDEV="/dev/mapper/${CRYPTDEV}" fi fi fi # Initialize LVM: if [ -x /sbin/vgscan ]; then /sbin/vgscan --mknodes --ignorelockingfailure sleep 10 /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 2>&1 ROOTDEV="/dev/mapper/${ROOTDEV}" fi fi fi # Resume state from swap if [ "$RESUMEDEV" != "" ]; then if ls -l $RESUMEDEV | grep -q "^l" ; then RESUMEDEV=`ls -l $RESUMEDEV | awk '{ print $NF }'` 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: echo 0x0100 > /proc/sys/kernel/real-root-dev mount -o ro -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 "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 if ps axc | grep -q udevd ; then killall udevd fi unset ERR umount /proc umount /sys echo "${INITRD}: exiting" exec switch_root /mnt /sbin/init $RUNLEVEL