1
0
Fork 0
mirror of git://slackware.nl/current.git synced 2025-01-29 08:36:40 +01:00
slackware-current/source/a/mkinitrd/mkinitrd

495 lines
16 KiB
Text
Raw Normal View History

#!/bin/sh
# Copyright 2004 Slackware Linux, Inc., Concord, CA, USA
# Copyright 2004 Patrick J. Volkerding, Concord, CA, USA
# Copyright 2007, 2008, 2009 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.
# Modified by Robby Workman <rworkman@slackware.com> 26 November 2007
# to add support for mkinitrd.conf - No additional license terms added
# Modified by Alan Hicks <alan@slackware.com> 27 November 2007 to enable
# passing arguments to kernel modules - No additional license terms added
# volkerdi - feel free to remove these :)
# Modified by Eric Hameleers <alien@slackware.com> 3 April 2008
# to add support custom keymaps - No additional license terms added
# Modified by Patrick Volkerding <volkerdi@slackware.com> 17 Dec 2008
# Added support to bail out if kernel modules are requested for a kernel
# version that is not installed (thanks to Eric Hameleers), be more
# verbose about showing modules added to the initrd (thanks to
# Ellington Santos), and if "mount" returns /dev/root as the root device,
# use readlink to resolve the device pointed to by the /dev/root
# symlink, changed modprobe to use --ignore-install to avoid catching
# custom "install" lines and causing /sbin/modprobe to be copied to the
# initrd (thanks to Ken Milmore).
# Of course, license terms remain unchanged.
MKINITRD_VERSION=1.3.4
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. :-)
-F Use the contents of /etc/mkinitrd.conf (optional)
If this is used in conjunction with any other options passed
on the command line, the command-line options will override
the config file options. See mkinitrd.conf(5) for details.
-c Clear the existing initrd tree first
-f Filesystem to use for root partition (must be used with -r)
--help Display this message
-h Device to resume from hibernation. Needs to be the name of
the swap partition holding the hibernation image.
-k Kernel version to use
-l Custom keymap to load. Like, 'nl' or 'de-latin1-nodeadkeys'
-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/)
-w Time to wait until all disks are detected
-C Use cryptsetup to unlock the underlying device of an
encrypted root filesystem (must be used with '-r' parameter).
Two scenarios are possible. (1) root filesystem was created on the
encrypted disk/LVM partition, example:
-C /dev/sda2 -r cryptroot
where /dev/sda2 is the encrypted partition and
the actual root device name in /etc/fstab is:
/dev/mapper/cryptroot
(2) the encrypted partition contains a LVM volume which holds the
root filesystem, example:
-C /dev/sda2 -r /dev/vg/root
where /dev/sda2 is the encrypted partition and
the actual root device name in /etc/fstab is:
/dev/vg/root
-L Add support for LVM partitions
-R Add support for RAID 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.29.3-smp kernel
modules for a system with an ext3 root partition on /dev/hdb3:
mkinitrd -c -k 2.6.29.3-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
# Make sure a kernel module directory exists:
mkdir -p $SOURCE_TREE/lib/modules/${KERNEL_VERSION}
# Add the initrd-tree skeleton:
( 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 ]; then
if [ -b /dev/$device ]; then
if [ -L /dev/$device ]; then
cp -a --parents $(readlink -e /dev/$device) $SOURCE_TREE
fi
cp -a --parents /dev/$device $SOURCE_TREE
fi
fi
done
}
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 ]; then
if [ -b /dev/$device ]; then
if [ -L /dev/$device ]; then
cp -a --parents $(readlink -e /dev/$device) $SOURCE_TREE
fi
cp -a --parents /dev/$device $SOURCE_TREE
fi
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
)
}
badconf_file() {
# This won't really help with what's *wrong* with the file,
# but it will at least give them a clue that there's a problem
echo "/etc/mkinitrd.conf is bad or does not exist."
echo "If the file does not exist, do not pass -F to mkinitrd."
exit 1
}
# 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 set from config file or 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 for the use config file option first or else the other command
# line options can not override /etc/mkinitrd.conf.
for opt in "$@"; do
if [ $opt = "-F" ]; then
if [ -e /etc/mkinitrd.conf ]; then
. /etc/mkinitrd.conf || badconf_file
else
badconf_file
fi
fi
done
# Parse options:
while [ ! -z "$1" ]; do
case $1 in
-c)
CLEAR_TREE=1
shift
;;
-f)
ROOTFS="$2"
shift 2
;;
-h)
RESUMEDEV="$2"
shift 2
;;
-k)
KERNEL_VERSION="$2"
shift 2
;;
-l)
KEYMAP="$2"
shift 2
;;
-m)
MODULE_LIST="$2"
shift 2
;;
-o)
OUTPUT_IMAGE="$2"
if [ ! "$(echo $OUTPUT_IMAGE | cut -b1)" = "/" ]; then
OUTPUT_IMAGE=$(pwd)/$OUTPUT_IMAGE
fi
shift 2
;;
-r)
ROOTDEV="$2"
shift 2
;;
-s)
SOURCE_TREE="$2"
shift 2
;;
-w)
WAIT="$2"
shift 2
;;
-C)
CRYPT=1
LUKSDEV="$2"
shift 2
;;
-L)
LVM=1
shift
;;
-R)
RAID=1
shift
;;
*) # unknown, prevent infinite loop
shift
;;
esac
done
# If kernel modules are needed but the kernel version is absent, exit now:
if [ ! -d /lib/modules/$KERNEL_VERSION ]; then
echo "ERROR: No /lib/modules/$KERNEL_VERSION kernel modules tree found for kernel \"$KERNEL_VERSION\""
exit 1
fi
# If clearing source tree was requested, do that first
if [ "$CLEAR_TREE" = "1" ]; then
clear_source_tree
fi
# 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 /
# (unless we find that values are already set in the initrd-tree):
if [ -z "$ROOTDEV" -a -z "$(cat $SOURCE_TREE/rootdev 2> /dev/null)" ]; then
ROOTDEV=$(mount | grep ' on / ' | cut -f 1 -d ' ')
if [ "$ROOTDEV" = "/dev/root" ]; then # find real root device
ROOTDEV="/dev/$(readlink /dev/root)"
fi
fi
if [ -z "$ROOTFS" -a -z "$(cat $SOURCE_TREE/rootfs 2> /dev/null)" ]; then
ROOTFS=$(mount | grep ' on / ' | cut -f 5 -d ' ')
fi
# If needed, write them in the initrd-tree:
if [ ! -z "$ROOTDEV" ]; then
echo $ROOTDEV > $SOURCE_TREE/rootdev
fi
if [ ! -z "$ROOTFS" ]; then
echo $ROOTFS > $SOURCE_TREE/rootfs
fi
# If $WAIT is not set, assume we need only one second
# to have all devices done
# (unless we find that value is already set in the initrd-tree):
if [ -z "$WAIT" -a -z "$(cat $SOURCE_TREE/wait-for-root)" ]; then
WAIT=1
fi
if [ ! -z "$WAIT" ]; then
echo $WAIT > $SOURCE_TREE/wait-for-root
fi
# Useful to know which initrd is running:
INITRD_NAME=$(basename $OUTPUT_IMAGE)
echo $INITRD_NAME > $SOURCE_TREE/initrd-name
# Fill /resumedev with the swap partition holding the hibernation image
if [ ! -z "$RESUMEDEV" ]; then
echo $RESUMEDEV > $SOURCE_TREE/resumedev
fi
# Add custom keymap support if one was given
if [ ! -z "$KEYMAP" ]; then
echo $KEYMAP > $SOURCE_TREE/keymap
cp /usr/share/mkinitrd/keymaps.tar.gz $SOURCE_TREE/etc/
fi
# If LUKSDEV was set in the config file, then we need to set CRYPT=1
if [ ! -z "$LUKSDEV" ]; then
CRYPT=1
fi
# Include RAID support in initrd
if [ ! -z "$RAID" ]; then
if [ -r /sbin/mdadm ]; then
mkdir -p $SOURCE_TREE/sbin
cp /sbin/mdadm $SOURCE_TREE/sbin/mdadm
chmod 755 $SOURCE_TREE/sbin/mdadm
else
echo "ERROR: mdadm binary is missing, RAID support not installed"
fi
fi
# 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
cp /sbin/dmsetup.static $SOURCE_TREE/sbin/dmsetup.static
( cd $SOURCE_TREE/sbin
ln -s lvm.static vgchange 2>/dev/null
ln -s lvm.static vgscan 2>/dev/null )
if [ -z "${MODULE_LIST}" ] ; then
MODULE_LIST="dm-mod"
elif ! 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 2>/dev/null
)
cat << EOF > $SOURCE_TREE/sbin/udevadm
#!/bin/sh
sleep 3
EOF
chmod 0755 $SOURCE_TREE/sbin/udevadm
if [ -z "${MODULE_LIST}" ] ; then
MODULE_LIST="dm-mod"
elif ! 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
# Count number of modules
# This INDEX number gives us an easy way to find individual
# modules and their arguments, as well as tells us how many
# times to run through the list
if ! echo $MODULE_LIST | grep ':' > /dev/null ; then # only 1 module specified
INDEX=1
else
INDEX=1
while [ ! "$(echo "$MODULE_LIST" | cut -f $INDEX -d ':' )" = "" ]; do
INDEX=$(expr $INDEX + 1)
done
INDEX=$(expr $INDEX - 1) # Don't include the null value
fi
# Wrap everything in a while loop
i=0
while [ $i -ne $INDEX ]; do
i=$(( $i + 1 ))
# FULL_MOD is the module plus any arguments (if any)
# MODULE is the module name
# ARGS is any optional arguments to be passed to the kernel
FULL_MOD="$(echo "$MODULE_LIST" | cut -d ':' -f $i)"
MODULE="$(echo "$FULL_MOD" | cut -d ' ' -f 1 )"
# Test for arguments
if echo "$FULL_MOD" | grep ' ' > /dev/null; then
ARGS=" $(echo "$FULL_MOD" | cut -d ' ' -f 2- )"
else
unset ARGS
fi
# Get MODULE deps and prepare insmod lines
/sbin/modprobe --set-version $KERNEL_VERSION --show-depends --ignore-install $MODULE 2> /dev/null \
| grep "^insmod " | 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)/")"
# Test to see if arguments should be passed
# Over-ride the previously defined LINE variable if so
if [ "$(basename $SRCMOD .ko)" = "$MODULE" ]; then
# SRCMOD and MODULE are same, ARGS can be passed
LINE="$LINE$ARGS"
fi
fi
if ! grep -qx "$LINE" $SOURCE_TREE/load_kernel_modules ; then
echo "$LINE" >> $SOURCE_TREE/load_kernel_modules
fi
if cp -a --parents $SRCMOD $SOURCE_TREE 2> /dev/null; then
echo "OK: $SRCMOD added."
else
echo "WARNING: Could not find module \"$SRCMOD\""
fi
done
done
fi
# And finally, build the initrd:
build_initrd_image