summaryrefslogblamecommitdiffstats
path: root/source/a/mkinitrd/init
blob: 0559932e97bd239d61a70e279cd00d8f39bc4307 (plain) (tree)





































































































































































































































                                                                                    
#!/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 >/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 >/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