#!/bin/sh # Copyright 2004 Slackware Linux, Inc., Concord, CA, USA # Copyright 2004 Patrick J. Volkerding, Concord, CA, USA # Copyright 2007 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. MKINITRD_VERSION=1.1.2 print_usage() { cat << EOF Usage: mkinitrd [OPTION] mkinitrd creates an initial ramdisk (actually an initramfs cpio+gzip archive) used to load kernel modules that are needed to mount the root filesystem, or other modules that might be needed before the root filesystem is available. Other binaries may be added to the initrd, and the script is easy to modify. Be creative. :-) -c Clear the existing initrd tree first -f Filesystem to use for root partition (must be used with -r) --help Display this message -k Kernel version to use -m A colon (:) delimited list of kernel modules to load. Additional options may be added to use when loading the kernel modules (but in this case the entire list must be wrapped with double quotes). Any dependencies of requested modules will also be added to the initrd. -o Output image (default /boot/initrd.gz) -r Root partition device (must be used with -f) -s Initrd source tree (default /boot/initrd-tree/) -C Use cryptsetup to enable the underlying device of an encrypted root partition. Requires '-r' parameter with the *mapped* device name as argument, like: -C /dev/sda2 -r cryptroot where the actual root device name in /etc/fstab is: /dev/mapper/cryptroot -L Add support for LVM partitions -V Display version number A simple example: Build an initrd for a reiserfs root partition: mkinitrd -c -m reiserfs Another example: Build an initrd image using Linux 2.6.20.11-smp kernel modules for a system with an ext3 root partition on /dev/hdb3: mkinitrd -c -k 2.6.20.11-smp -m mbcache:jbd:ext3 -f ext3 -r /dev/hdb3 Note that if you are already logged in with /dev/hdb3 as your / partition, and it is running ext3, this command works just the same: mkinitrd -c -m ext3 If run without options, mkinitrd will rebuild an initrd image using the contents of the $SOURCE_TREE directory, or, if that directory does not exist it will be created and populated, and then mkinitrd will exit. EOF } create_new_source_tree() { mkdir -p $SOURCE_TREE ( cd $SOURCE_TREE ; tar xzf /usr/share/mkinitrd/initrd-tree.tar.gz ) # Make sure we have any block devices that might be needed: SLOPPY_DEV_LIST=$(cat /proc/partitions) for device in $SLOPPY_DEV_LIST ; do if [ ! -r $SOURCE_TREE/dev/$device -a -b /dev/$device ]; then cp -a /dev/$device $SOURCE_TREE/dev fi done # Make sure a kernel module directory exists: mkdir -p $SOURCE_TREE/lib/modules/${KERNEL_VERSION} } clear_source_tree() { if [ -d "$SOURCE_TREE" ]; then rm -rf $SOURCE_TREE fi } build_initrd_image() { # Make sure we have any block devices that might be needed: SLOPPY_DEV_LIST=$(cat /proc/partitions) for device in $SLOPPY_DEV_LIST ; do if [ ! -r $SOURCE_TREE/dev/$device -a -b /dev/$device ]; then cp -a /dev/$device $SOURCE_TREE/dev fi done # Wrap the initrd as an initramfs image and move it into place: ( cd $SOURCE_TREE rm -f $OUTPUT_IMAGE find . | cpio -o -H newc | gzip -9c > $OUTPUT_IMAGE ) } # If --help is given, print_usage and exit: if echo $* | grep -wq '\--help' ; then print_usage exit 0 fi # If -V given, print version and exit: if echo $* | grep -wq '\-V' ; then echo "mkinitrd version $MKINITRD_VERSION" exit 0 fi # Default values if these aren't previously set. # Might be changed by -s and -o options, too. SOURCE_TREE=${SOURCE_TREE:-/boot/initrd-tree} OUTPUT_IMAGE=${OUTPUT_IMAGE:-/boot/initrd.gz} KERNEL_VERSION=${KERNEL_VERSION:-"$(uname -r)"} # Default actions without options: if [ -z "$1" ]; then # If the output tree doesn't exist, create it and then exit: if [ ! -d $SOURCE_TREE ]; then echo "Nothing found at location $SOURCE_TREE, so we will create an" echo -n "initrd directory structure there... " create_new_source_tree echo "done." echo echo "Now cd to $SOURCE_TREE and install some modules in your" echo "module directory (lib/modules/${KERNEL_VERSION}). Then see init" echo "for more information (there are a few other files to edit)." echo "Finally, run mkinitrd again once the initrd-tree is ready," echo "and $OUTPUT_IMAGE will be created from it." echo exit 0 else # If the source tree does exist, the default is to build the initrd # image from it and then exit: build_initrd_image echo "$OUTPUT_IMAGE created." echo "Be sure to run lilo again if you use it." exit 0 fi fi # default no-option actions # Parse options: while [ ! -z "$1" ]; do case $1 in -c) clear_source_tree shift ;; -f) ROOTFS="$2" shift 2 ;; -k) KERNEL_VERSION="$2" shift 2 ;; -m) MODULE_LIST="$2" shift 2 ;; -o) OUTPUT_IMAGE="$2" shift 2 ;; -r) ROOTDEV="$2" shift 2 ;; -s) SOURCE_TREE="$2" shift 2 ;; -C) CRYPT=1 LUKSDEV="$2" shift 2 ;; -L) LVM=1 shift ;; *) # unknown, prevent infinite loop shift ;; esac done # If there's no $SOURCE_TREE, make one now: if [ ! -d "$SOURCE_TREE" ]; then create_new_source_tree fi # If $ROOTDEV and $ROOTFS are not set, assume we want the # values for the currently mounted /: if [ -z "$ROOTDEV" ]; then ROOTDEV=$(mount | grep -w / | cut -f 1 -d ' ') fi if [ -z "$ROOTFS" ]; then ROOTFS=$(mount | grep -w / | cut -f 5 -d ' ') fi # Next, write them in the initrd-tree: echo $ROOTDEV > $SOURCE_TREE/rootdev echo $ROOTFS > $SOURCE_TREE/rootfs # Useful to know which initrd is running: INITRD_NAME=$(basename $OUTPUT_IMAGE) echo $INITRD_NAME > $SOURCE_TREE/initrd-name # Include LVM support in initrd if [ ! -z "$LVM" ]; then if [ -f /sbin/lvm.static ]; then mkdir -p $SOURCE_TREE/sbin cp /sbin/lvm.static $SOURCE_TREE/sbin/lvm.static ( cd $SOURCE_TREE/sbin ln -s lvm.static vgchange ln -s lvm.static vgscan ) if ! echo ${MODULE_LIST} | grep -q dm-mod ; then MODULE_LIST="$MODULE_LIST:dm-mod" fi else echo "LVM static binary is missing, LVM support isn't installed" fi fi # Include cryptsetup (LUKS) support in initrd if [ ! -z "$CRYPT" ]; then if [ -e /sbin/cryptsetup.static ]; then mkdir -p $SOURCE_TREE/sbin cp /sbin/cryptsetup.static $SOURCE_TREE/sbin/cryptsetup.static ( cd $SOURCE_TREE/sbin ln -s cryptsetup.static cryptsetup ) if ! echo ${MODULE_LIST} | grep -q dm-mod ; then MODULE_LIST="$MODULE_LIST:dm-mod" fi # Write the underlying luks device to the initrd-tree: echo $LUKSDEV > $SOURCE_TREE/luksdev else echo "Cryptsetup static binary is missing, CRYPT support isn't installed" fi fi # Make module directory: if [ ! -d $SOURCE_TREE/lib/modules/$KERNEL_VERSION ]; then mkdir -p $SOURCE_TREE/lib/modules/$KERNEL_VERSION fi # If a module list was given, copy the modules into place: if [ ! -z "$MODULE_LIST" ]; then if grep -q "#insmod /lib/modules/2.6.18.8-smp/reiserfs.ko" $SOURCE_TREE/load_kernel_modules ; then rm -f $SOURCE_TREE/load_kernel_modules touch $SOURCE_TREE/load_kernel_modules chmod 755 $SOURCE_TREE/load_kernel_modules echo "# This is a script used to load the kernel modules." >> $SOURCE_TREE/load_kernel_modules echo "# To use it, chmod it 755, and then add the insmod" >> $SOURCE_TREE/load_kernel_modules echo "# lines needed to load your modules, like this:" >> $SOURCE_TREE/load_kernel_modules echo >> $SOURCE_TREE/load_kernel_modules fi for MODULE in $(echo $MODULE_LIST | tr : \ ); do /sbin/modprobe -q --set-version $KERNEL_VERSION --show-depends $MODULE done | cut -f 2 -d ' ' | while read SRCMOD; do if ! grep -q "${SRCMOD}" $SOURCE_TREE/load_kernel_modules 2>/dev/null ; then LINE="$(echo "insmod -v $SRCMOD" | sed -e "s/$KERNEL_VERSION/\$(uname -r)/")" if ! grep -qx "$LINE" $SOURCE_TREE/load_kernel_modules ; then echo "$LINE" >> $SOURCE_TREE/load_kernel_modules fi fi if [ -r "$SRCMOD" ]; then cp -a --parents $SRCMOD $SOURCE_TREE else echo "WARNING: Could not find module \"$SRCMOD\"" fi done fi # And finally, build the initrd: build_initrd_image