#!/bin/bash # # Generator script for a dracut initramfs # Tries to retain some degree of compatibility with the command line # of the various mkinitrd implementations out there # # Copyright 2005-2009 Red Hat, Inc. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # usage() { # 80x25 linebreak here ^ echo "Usage: $0 [OPTION]... Creates initial ramdisk images for preloading modules -f, --force Overwrite existing initramfs file. -m, --modules [LIST] Specify a space-separated list of dracut modules to call when building the initramfs. Modules are located in /usr/share/dracut/modules.d. -o, --omit [LIST] Omit a space-separated list of dracut modules. -a, --add [LIST] Add a space-separated list of dracut modules. -d, --drivers [LIST] Specify a space-separated list of kernel modules to exclusively include in the initramfs. --add-drivers [LIST] Specify a space-separated list of kernel modules to add to the initramfs. --filesystems [LIST] Specify a space-separated list of kernel filesystem modules to exclusively include in the generic initramfs. -k, --kmoddir [DIR] Specify the directory, where to look for kernel modules --fwdir [DIR] Specify additional directories, where to look for firmwares, separated by : --kernel-only Only install kernel drivers and firmware files --no-kernel Do not install kernel drivers and firmware files --ignore-kernel-modules Don't try to load modules. It automatically implies '--no-kernel'. It's assumed that everything needed is built into kernel. --strip Strip binaries in the initramfs --nostrip Do not strip binaries in the initramfs (default) --mdadmconf Include local /etc/mdadm.conf --nomdadmconf Do not include local /etc/mdadm.conf --lvmconf Include local /etc/lvm/lvm.conf --nolvmconf Do not include local /etc/lvm/lvm.conf -h, --help This message --debug Output debug information of the build process -v, --verbose Verbose output during the build process -c, --conf [FILE] Specify configuration file to use. Default: /etc/dracut.conf --confdir [DIR] Specify configuration directory to use *.conf files from. Default: /etc/dracut.conf.d -l, --local Local mode. Use modules from the current working directory instead of the system-wide installed in /usr/share/dracut/modules.d. Useful when running dracut from a git checkout. -H, --hostonly Host-Only mode: Install only what is needed for booting the local host instead of a generic host. --fstab Use /etc/fstab to determine the root device. -i, --include [SOURCE] [TARGET] Include the files in the SOURCE directory into the Target directory in the final initramfs. -I, --install [LIST] Install the space separated list of files into the initramfs. --gzip Compress the generated initramfs using gzip. This will be done by default, unless another compression option or --no-compress is passed. --bzip2 Compress the generated initramfs using bzip2. Make sure your kernel has bzip2 decompression support compiled in, otherwise you will not be able to boot. --lzma Compress the generated initramfs using lzma. Make sure your kernel has lzma support compiled in, otherwise you will not be able to boot. --no-compress Do not compress the generated initramfs. This will override any other compression options. " } # Little helper function for reading args from the commandline. # it automatically handles -a b and -a=b variants, and returns 1 if # we need to shift $3. read_arg() { # $1 = arg name # $2 = arg value # $3 = arg parameter local rematch='^[^=]*=(.*)$' if [[ $2 =~ $rematch ]]; then read "$1" <<< "${BASH_REMATCH[1]}" else read "$1" <<< "$3" # There is no way to shift our callers args, so # return 1 to indicate they should do it instead. return 1 fi } while (($# > 0)); do case ${1%%=*} in -m|--modules) read_arg dracutmodules_l "$@" || shift;; -o|--omit) read_arg omit_dracutmodules_l "$@" || shift;; -a|--add) read_arg add_dracutmodules_l "$@" || shift;; -d|--drivers) read_arg drivers_l "$@" || shift;; --add-drivers) read_arg add_drivers_l "$@" || shift;; --filesystems) read_arg filesystems_l "$@" || shift;; -k|--kmoddir) read_arg drivers_dir_l "$@" || shift;; -c|--conf) read_arg conffile "$@" || shift;; --confdir) read_arg confdir "$@" || shift;; -I|--install) read_arg install_items "$@" || shift;; --fwdir) read_arg fw_dir_l "$@" || shift;; -f|--force) force=yes;; --kernel-only) kernel_only="yes"; no_kernel="no";; --no-kernel) kernel_only="no"; no_kernel="yes";; --strip) do_strip_l="yes";; --nostrip) do_strip_l="no";; --mdadmconf) mdadmconf_l="yes";; --nomdadmconf) mdadmconf_l="no";; --lvmconf) lvmconf_l="yes";; --nolvmconf) lvmconf_l="no";; --debug) debug="yes";; -v|--verbose) beverbose="yes";; -l|--local) allowlocal="yes" ;; -H|--hostonly) hostonly_l="yes" ;; --fstab) use_fstab_l="yes" ;; -h|--help) usage; exit 1 ;; -i|--include) include_src="$2"; include_target="$3"; shift 2;; --bzip2) [[ $compress != cat ]] && compress="bzip2 -9";; --lzma) [[ $compress != cat ]] && compress="lzma -9";; --no-compress) compress="cat";; --gzip) if [[ $compress != cat ]]; then type pigz > /dev/null 2>&1 && compress="pigz -9" || \ compress="gzip -9" fi;; --ignore-kernel-modules) kernel_only="no"; no_kernel="yes" ignore_kmodules="yes" omit_dracutmodules_l+=\ kernel-modules ;; -*) printf "\nUnknown option: %s\n\n" "$1" >&2; usage; exit 1;; *) break ;; esac shift done PATH=/sbin:/bin:/usr/sbin:/usr/bin export PATH [[ $debug ]] && { export PS4='${BASH_SOURCE}@${LINENO}(${FUNCNAME[0]}): '; set -x } [[ $dracutbasedir ]] || dracutbasedir=/usr/share/dracut [[ $allowlocal && -f "$(readlink -f ${0%/*})/dracut-functions" ]] && dracutbasedir="${0%/*}" # if we were not passed a config file, try the default one if [[ ! -f $conffile ]]; then [[ $allowlocal ]] && conffile="$dracutbasedir/dracut.conf" || \ conffile="/etc/dracut.conf" fi if [[ ! -d $confdir ]]; then [[ $allowlocal ]] && confdir="$dracutbasedir/dracut.conf.d" || \ confdir="/etc/dracut.conf.d" fi # source our config file [[ -f $conffile ]] && . "$conffile" # source our config dir if [[ $confdir && -d $confdir ]]; then for f in "$confdir"/*.conf; do [[ -e $f ]] && . "$f" done fi # these optins add to the stuff in the config file [[ $add_dracutmodules_l ]] && add_dracutmodules+=" $add_dracutmodules_l" [[ $add_drivers_l ]] && add_drivers+=" $add_drivers_l" # these options override the stuff in the config file [[ $dracutmodules_l ]] && dracutmodules=$dracutmodules_l [[ $omit_dracutmodules_l ]] && omit_dracutmodules=$omit_dracutmodules_l [[ $drivers_l ]] && drivers=$drivers_l [[ $filesystems_l ]] && filesystems=$filesystems_l [[ $drivers_dir_l ]] && drivers_dir=$drivers_dir_l [[ $fw_dir_l ]] && fw_dir=$fw_dir_l [[ $do_strip_l ]] && do_strip=$do_strip_l [[ $hostonly_l ]] && hostonly=$hostonly_l [[ $use_fstab_l ]] && use_fstab=$use_fstab_l [[ $mdadmconf_l ]] && mdadmconf=$mdadmconf_l [[ $lvmconf_l ]] && lvmconf=$lvmconf_l [[ $dracutbasedir ]] || dracutbasedir=/usr/share/dracut [[ $fw_dir ]] || fw_dir=/lib/firmware [[ $do_strip ]] || do_strip=no # eliminate IFS hackery when messing with fw_dir fw_dir=${fw_dir//:/ } [[ $hostonly = yes ]] && hostonly="-h" [[ $hostonly != "-h" ]] && unset hostonly [[ $compress ]] || compress="gzip -9" if [[ -f $dracutbasedir/dracut-functions ]]; then . $dracutbasedir/dracut-functions else echo "Cannot find $dracutbasedir/dracut-functions. Are you running from a git checkout?" echo "Try passing -l as an argument to $0" exit 1 fi dracutfunctions=$dracutbasedir/dracut-functions export dracutfunctions # Detect lib paths [[ $libdir ]] || for libdir in /lib64 /lib; do [[ -d $libdir ]] && break done || { derror 'No lib directory?!!!' exit 1 } [[ $usrlibdir ]] || for usrlibdir in /usr/lib64 /usr/lib; do [[ -d $usrlibdir ]] && break done || dwarning 'No usr/lib directory!' # This is kinda legacy -- eventually it should go away. case $dracutmodules in ""|auto) dracutmodules="all" ;; esac [[ $2 ]] && kernel=$2 || kernel=$(uname -r) [[ $1 ]] && outfile=$1 || outfile="/boot/initramfs-$kernel.img" abs_outfile=$(readlink -f "$outfile") && outfile="$abs_outfile" srcmods="/lib/modules/$kernel/" [[ $drivers_dir ]] && { if vercmp $(modprobe --version | cut -d' ' -f3) lt 3.7; then derror 'To use --kmoddir option module-init-tools >= 3.7 is required.' exit 1 fi srcmods="$drivers_dir" } export srcmods if [[ -f $outfile && ! $force ]]; then echo "Will not override existing initramfs ($outfile) without --force" exit 1 fi outdir=${outfile%/*} if [[ ! -d "$outdir" ]]; then echo "Can't write $outfile: Directory $outdir does not exist." exit 1 elif [[ ! -w "$outdir" ]]; then echo "No permission to write $outdir." exit 1 elif [[ -f "$outfile" && ! -w "$outfile" ]]; then echo "No permission to write $outfile." exit 1 fi hookdirs="cmdline pre-udev pre-trigger netroot pre-mount pre-pivot mount emergency" [[ $TMPDIR && ! -w $TMPDIR ]] && unset TMPDIR readonly initdir=$(mktemp -d -t initramfs.XXXXXX) trap 'ret=$?;rm -rf "$initdir";exit $ret;' EXIT # clean up after ourselves no matter how we die. trap 'exit 1;' SIGINT # clean up after ourselves no matter how we die. # Need to be able to have non-root users read stuff (rpcbind etc) chmod 755 "$initdir" export initdir hookdirs dracutbasedir dracutmodules drivers \ fw_dir drivers_dir debug beverbose no_kernel kernel_only \ add_drivers mdadmconf lvmconf filesystems ignore_kmodules \ use_fstab libdir usrlibdir if [[ $kernel_only != yes ]]; then # Create some directory structure first for d in bin sbin usr/bin usr/sbin usr/lib etc proc sys sysroot tmp dev/pts var/run; do inst_dir "/$d"; done fi # check all our modules to see if they should be sourced. # This builds a list of modules that we will install next. check_modules # source our modules. for moddir in "$dracutbasedir/modules.d"/[0-9][0-9]*; do mod=${moddir##*/}; mod=${mod#[0-9][0-9]} if strstr "$mods_to_load" " $mod "; then dinfo "*** Sourcing module $mod" if [[ $kernel_only = yes ]]; then [[ -x $moddir/installkernel ]] && . "$moddir/installkernel" else . "$moddir/install" if [[ $no_kernel != yes && -x $moddir/installkernel ]]; then . "$moddir/installkernel" fi fi mods_to_load=${mods_to_load// $mod /} fi done unset moddir ## final stuff that has to happen # generate module dependencies for the initrd if [[ -d $initdir/lib/modules/$kernel ]] && \ ! depmod -a -b "$initdir" $kernel; then derror "\"depmod -a $kernel\" failed." exit 1 fi if [[ $include_src && $include_target ]]; then mkdir -p "$initdir$include_target" cp -a -t "$initdir$include_target" "$include_src"/* fi for item in $install_items; do dracut_install "$item" done unset item # make sure that library links are correct and up to date cp -ar /etc/ld.so.conf* "$initdir"/etc ldconfig -r "$initdir" || [[ $UID != "0" ]] && dinfo "ldconfig might need uid=0 (root) for chroot()" [[ $beverbose = yes ]] && (du -c "$initdir" | sort -n) # strip binaries if [[ $do_strip = yes ]] ; then for p in strip grep find; do if ! type -P $p >/dev/null; then derror "Could not find '$p'. You should run $0 with '--nostrip'." do_strip=no fi done fi if [[ $do_strip = yes ]] ; then for f in $(find "$initdir" -type f \( -perm -0100 -or -perm -0010 -or -perm -0001 -or -path '*/lib/modules/*.ko' \) ); do dinfo "Stripping $f" strip -g "$f" 2>/dev/null|| : # # FIXME: only strip -g for now # #strip -g --strip-unneeded "$f" || : #note="-R .note" #if objdump -h $f | grep '^[ ]*[0-9]*[ ]*.note[ ]' -A 1 | \ # grep -q ALLOC; then # note= #fi #strip -R .comment $note "$f" || : done fi type hardlink &>/dev/null && { hardlink "$initdir" 2>&1 } if ! ( cd "$initdir"; find . |cpio -R 0:0 -H newc -o --quiet | \ $compress > "$outfile"; ); then derror "dracut: creation of $outfile failed" exit 1 fi [[ $beverbose = yes ]] && ls -lh "$outfile" exit 0