Update to 032
[platform/upstream/dracut.git] / dracut.sh
index 64cd75e..117f877 100755 (executable)
--- a/dracut.sh
+++ b/dracut.sh
@@ -7,7 +7,7 @@
 # of the various mkinitrd implementations out there
 #
 
-# Copyright 2005-2010 Red Hat, Inc.  All rights reserved.
+# Copyright 2005-2013 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
@@ -24,7 +24,9 @@
 #
 
 # store for logging
-dracut_args="$@"
+dracut_args=( "$@" )
+
+set -o pipefail
 
 usage() {
     [[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut
@@ -34,43 +36,78 @@ usage() {
 
 #                                                       80x25 linebreak here ^
     cat << EOF
-Usage: $0 [OPTION]... <initramfs> <kernel-version>
+Usage: $0 [OPTION]... [<initramfs> [<kernel-version>]]
+
+Version: $DRACUT_VERSION
+
+Creates initial ramdisk images for preloading modules
+
+  -h, --help  Display all options
+
+If a [LIST] has multiple arguments, then you have to put these in quotes.
+
+For example:
+
+    # dracut --add-drivers "module1 module2"  ...
+
+EOF
+}
+
+long_usage() {
+    [[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut
+    if [[ -f $dracutbasedir/dracut-version.sh ]]; then
+        . $dracutbasedir/dracut-version.sh
+    fi
+
+#                                                       80x25 linebreak here ^
+    cat << EOF
+Usage: $0 [OPTION]... [<initramfs> [<kernel-version>]]
 
 Version: $DRACUT_VERSION
 
 Creates initial ramdisk images for preloading modules
 
+  --kver [VERSION]      Set kernel version to [VERSION].
   -f, --force           Overwrite existing initramfs file.
+  -a, --add [LIST]      Add a space-separated list of dracut modules.
   -m, --modules [LIST]  Specify a space-separated list of dracut modules to
                          call when building the initramfs. Modules are located
                          in /usr/lib/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.
+  --force-add [LIST]    Force to add a space-separated list of dracut modules
+                         to the default set of modules, when -H is specified.
   -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.
+                         exclusively include in the initramfs.
+  --add-drivers [LIST]  Specify a space-separated list of kernel
+                         modules to add to the initramfs.
   --omit-drivers [LIST] Specify a space-separated list of kernel
-                        modules not to add to the initramfs.
+                         modules not to add to the initramfs.
   --filesystems [LIST]  Specify a space-separated list of kernel filesystem
-                        modules to exclusively include in the generic
-                        initramfs.
+                         modules to exclusively include in the generic
+                         initramfs.
   -k, --kmoddir [DIR]   Specify the directory, where to look for kernel
-                        modules
+                         modules
   --fwdir [DIR]         Specify additional directories, where to look for
-                        firmwares, separated by :
+                         firmwares, separated by :
   --kernel-only         Only install kernel drivers and firmware files
   --no-kernel           Do not install kernel drivers and firmware files
+  --print-cmdline       Print the kernel command line for the given disk layout
+  --early-microcode     Combine early microcode with ramdisk
+  --no-early-microcode  Do not combine early microcode with ramdisk
+  --kernel-cmdline [PARAMETERS] Specify default kernel command line parameters
   --strip               Strip binaries in the initramfs
-  --nostrip             Do not strip binaries in the initramfs (default)
+  --nostrip             Do not strip binaries in the initramfs
+  --hardlink            Hardlink files in the initramfs
+  --nohardlink          Do not hardlink files in the initramfs
   --prefix [DIR]        Prefix initramfs files with [DIR]
-  --noprefix            Do not prefix initramfs files (default)
+  --noprefix            Do not prefix initramfs files
   --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
   --fscks [LIST]        Add a space-separated list of fsck helpers.
   --nofscks             Inhibit installation of any fsck helpers.
+  --ro-mnt              Mount / and /usr read-only by default.
   -h, --help            This message
   --debug               Output debug information of the build process
   --profile             Output profile information of the build process
@@ -79,11 +116,11 @@ Creates initial ramdisk images for preloading modules
                          1 - only fatal errors
                          2 - all errors
                          3 - warnings
-                         4 - info (default)
+                         4 - info
                          5 - debug info (here starts lots of output)
                          6 - trace info (and even more)
-  -v, --verbose         Increase verbosity level (default is info(4))
-  -q, --quiet           Decrease verbosity level (default is info(4))
+  -v, --verbose         Increase verbosity level
+  -q, --quiet           Decrease verbosity level
   -c, --conf [FILE]     Specify configuration file to use.
                          Default: /etc/dracut.conf
   --confdir [DIR]       Specify configuration directory to use *.conf files
@@ -95,13 +132,18 @@ Creates initial ramdisk images for preloading modules
                          /usr/lib/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.
-  --no-hostonly         Disables Host-Only mode
+                        booting the local host instead of a generic host.
+  -N, --no-hostonly     Disables Host-Only mode
+  --persistent-policy [POLICY]
+                        Use [POLICY] to address disks and partitions.
+                        POLICY can be any directory name found in /dev/disk.
+                        E.g. "by-uuid", "by-label"
   --fstab               Use /etc/fstab to determine the root device.
   --add-fstab [FILE]    Add file to the initramfs fstab
   --mount "[DEV] [MP] [FSTYPE] [FSOPTS]"
                         Mount device [DEV] on mountpoint [MP] with filesystem
                         [FSTYPE] and options [FSOPTS] in the initramfs
+  --add-device "[DEV]"  Bring up [DEV] in initramfs
   -i, --include [SOURCE] [TARGET]
                         Include the files in the SOURCE directory into the
                          Target directory in the final initramfs.
@@ -135,8 +177,11 @@ Creates initial ramdisk images for preloading modules
   --sshkey [SSHKEY]     Add ssh key to initramfs (use with ssh-client module)
 
 If [LIST] has multiple arguments, then you have to put these in quotes.
+
 For example:
-# dracut --add-drivers "module1 module2"  ...
+
+    # dracut --add-drivers "module1 module2"  ...
+
 EOF
 }
 
@@ -147,9 +192,10 @@ EOF
 # example:
 # push stack 1 2 "3 4"
 push() {
+    local _i
     local __stack=$1; shift
-    for i in "$@"; do
-        eval ${__stack}'[${#'${__stack}'[@]}]="$i"'
+    for _i in "$@"; do
+        eval ${__stack}'[${#'${__stack}'[@]}]="$_i"'
     done
 }
 
@@ -165,16 +211,16 @@ push() {
 pop() {
     local __stack=$1; shift
     local __resultvar=$1
-    local myresult;
+    local _value;
     # check for empty stack
     eval '[[ ${#'${__stack}'[@]} -eq 0 ]] && return 1'
 
-    eval myresult='${'${__stack}'[${#'${__stack}'[@]}-1]}'
+    eval _value='${'${__stack}'[${#'${__stack}'[@]}-1]}'
 
     if [[ "$__resultvar" ]]; then
-        eval $__resultvar="'$myresult'"
+        eval $__resultvar="'$_value'"
     else
-        echo "$myresult"
+        printf "%s" "$_value"
     fi
     eval unset ${__stack}'[${#'${__stack}'[@]}-1]'
     return 0
@@ -198,57 +244,158 @@ read_arg() {
     fi
 }
 
-# Little helper function for reading args from the commandline to a stack.
-# it automatically handles -a b and -a=b variants, and returns 1 if
-# we need to shift $3.
-push_arg() {
-    # $1 = arg name
-    # $2 = arg value
-    # $3 = arg parameter
-    local rematch='^[^=]*=(.*)$'
-    if [[ $2 =~ $rematch ]]; then
-        push "$1" "${BASH_REMATCH[1]}"
-    else
-        push "$1" "$3"
-        # There is no way to shift our callers args, so
-        # return 1 to indicate they should do it instead.
-        return 1
-    fi
+dropindirs_sort()
+{
+    local suffix=$1; shift
+    local -a files
+    local f d
+
+    for d in "$@"; do
+        for i in "$d/"*"$suffix"; do
+            if [[ -e "$i" ]]; then
+                printf "%s\n" "${i##*/}"
+            fi
+        done
+    done | sort -Vu | {
+        readarray -t files
+
+        for f in "${files[@]}"; do
+            for d in "$@"; do
+                if [[ -e "$d/$f" ]]; then
+                    printf "%s\n" "$d/$f"
+                    continue 2
+                fi
+            done
+        done
+    }
 }
 
 verbosity_mod_l=0
 unset kernel
 unset outfile
 
-while (($# > 0)); do
-    case ${1%%=*} in
-        -a|--add)      push_arg add_dracutmodules_l  "$@" || shift;;
-        --force-add)   push_arg force_add_dracutmodules_l  "$@" || shift;;
-        --add-drivers) push_arg add_drivers_l        "$@" || shift;;
-        --omit-drivers) push_arg omit_drivers_l      "$@" || shift;;
-        -m|--modules)  push_arg dracutmodules_l      "$@" || shift;;
-        -o|--omit)     push_arg omit_dracutmodules_l "$@" || shift;;
-        -d|--drivers)  push_arg drivers_l            "$@" || shift;;
-        --filesystems) push_arg filesystems_l        "$@" || shift;;
-        -I|--install)  push_arg install_items_l      "$@" || shift;;
-        --fwdir)       push_arg fw_dir_l             "$@" || shift;;
-        --libdirs)     push_arg libdirs_l            "$@" || shift;;
-        --fscks)       push_arg fscks_l              "$@" || shift;;
-        --add-fstab)   push_arg add_fstab_l          "$@" || shift;;
-        --mount)       push_arg fstab_lines          "$@" || shift;;
+# Workaround -i, --include taking 2 arguments
+set -- "${@/--include/++include}"
+
+# This prevents any long argument ending with "-i"
+# -i, like --opt-i but I think we can just prevent that
+set -- "${@/%-i/++include}"
+
+TEMP=$(unset POSIXLY_CORRECT; getopt \
+    -o "a:m:o:d:I:k:c:L:fvqlHhMN" \
+    --long kver: \
+    --long add: \
+    --long force-add: \
+    --long add-drivers: \
+    --long omit-drivers: \
+    --long modules: \
+    --long omit: \
+    --long drivers: \
+    --long filesystems: \
+    --long install: \
+    --long fwdir: \
+    --long libdirs: \
+    --long fscks: \
+    --long add-fstab: \
+    --long mount: \
+    --long device: \
+    --long nofscks: \
+    --long ro-mnt \
+    --long kmoddir: \
+    --long conf: \
+    --long confdir: \
+    --long tmpdir: \
+    --long stdlog: \
+    --long compress: \
+    --long prefix: \
+    --long force \
+    --long kernel-only \
+    --long no-kernel \
+    --long print-cmdline \
+    --long kernel-cmdline: \
+    --long strip \
+    --long nostrip \
+    --long hardlink \
+    --long nohardlink \
+    --long noprefix \
+    --long mdadmconf \
+    --long nomdadmconf \
+    --long lvmconf \
+    --long nolvmconf \
+    --long debug \
+    --long profile \
+    --long sshkey: \
+    --long verbose \
+    --long quiet \
+    --long local \
+    --long hostonly \
+    --long host-only \
+    --long no-hostonly \
+    --long no-host-only \
+    --long persistent-policy: \
+    --long fstab \
+    --long help \
+    --long bzip2 \
+    --long lzma \
+    --long xz \
+    --long no-compress \
+    --long gzip \
+    --long list-modules \
+    --long show-modules \
+    --long keep \
+    --long printsize \
+    --long regenerate-all \
+    --long noimageifnotneeded \
+    --long early-microcode \
+    --long no-early-microcode \
+    -- "$@")
+
+if (( $? != 0 )); then
+    usage
+    exit 1
+fi
+
+eval set -- "$TEMP"
+
+while :; do
+    case $1 in
+        --kver)        kernel="$2"; shift;;
+        -a|--add)      push add_dracutmodules_l  "$2"; shift;;
+        --force-add)   push force_add_dracutmodules_l  "$2"; shift;;
+        --add-drivers) push add_drivers_l        "$2"; shift;;
+        --omit-drivers) push omit_drivers_l      "$2"; shift;;
+        -m|--modules)  push dracutmodules_l      "$2"; shift;;
+        -o|--omit)     push omit_dracutmodules_l "$2"; shift;;
+        -d|--drivers)  push drivers_l            "$2"; shift;;
+        --filesystems) push filesystems_l        "$2"; shift;;
+        -I|--install)  push install_items_l      "$2"; shift;;
+        --fwdir)       push fw_dir_l             "$2"; shift;;
+        --libdirs)     push libdirs_l            "$2"; shift;;
+        --fscks)       push fscks_l              "$2"; shift;;
+        --add-fstab)   push add_fstab_l          "$2"; shift;;
+        --mount)       push fstab_lines          "$2"; shift;;
+        --add-device|--device)
+                       push add_device_l         "$2"; shift;;
+        --kernel-cmdline) push kernel_cmdline_l  "$2"; shift;;
         --nofscks)     nofscks_l="yes";;
-        -k|--kmoddir)  read_arg drivers_dir_l        "$@" || shift;;
-        -c|--conf)     read_arg conffile             "$@" || shift;;
-        --confdir)     read_arg confdir              "$@" || shift;;
-        --tmpdir)      read_arg tmpdir_l             "$@" || shift;;
-        -L|--stdlog)   read_arg stdloglvl_l          "$@" || shift;;
-        --compress)    read_arg compress_l           "$@" || shift;;
-        --prefix)      read_arg prefix_l             "$@" || shift;;
+        --ro-mnt)      ro_mnt_l="yes";;
+        -k|--kmoddir)  drivers_dir_l="$2"; shift;;
+        -c|--conf)     conffile="$2"; shift;;
+        --confdir)     confdir="$2"; shift;;
+        --tmpdir)      tmpdir_l="$2"; shift;;
+        -L|--stdlog)   stdloglvl_l="$2"; shift;;
+        --compress)    compress_l="$2"; shift;;
+        --prefix)      prefix_l="$2"; shift;;
         -f|--force)    force=yes;;
         --kernel-only) kernel_only="yes"; no_kernel="no";;
         --no-kernel)   kernel_only="no"; no_kernel="yes";;
+        --print-cmdline) print_cmdline="yes"; hostonly_l="yes"; kernel_only="yes"; no_kernel="yes";;
+        --early-microcode) early_microcode_l="yes";;
+        --no-early-microcode) early_microcode_l="no";;
         --strip)       do_strip_l="yes";;
         --nostrip)     do_strip_l="no";;
+        --hardlink)    do_hardlink_l="yes";;
+        --nohardlink)  do_hardlink_l="no";;
         --noprefix)    prefix_l="/";;
         --mdadmconf)   mdadmconf_l="yes";;
         --nomdadmconf) mdadmconf_l="no";;
@@ -256,66 +403,135 @@ while (($# > 0)); do
         --nolvmconf)   lvmconf_l="no";;
         --debug)       debug="yes";;
         --profile)     profile="yes";;
-        --sshkey)      read_arg sshkey   "$@" || shift;;
+        --sshkey)      sshkey="$2"; shift;;
         -v|--verbose)  ((verbosity_mod_l++));;
         -q|--quiet)    ((verbosity_mod_l--));;
         -l|--local)
                        allowlocal="yes"
-                       [[ -f "$(readlink -f ${0%/*})/dracut-functions.sh" ]] \
-                           && dracutbasedir="$(readlink -f ${0%/*})"
+                       [[ -f "$(readlink -f "${0%/*}")/dracut-functions.sh" ]] \
+                           && dracutbasedir="$(readlink -f "${0%/*}")"
                        ;;
-        -H|--hostonly) hostonly_l="yes" ;;
-        --no-hostonly) hostonly_l="no" ;;
+        -H|--hostonly|--host-only)
+                       hostonly_l="yes" ;;
+        -N|--no-hostonly|--no-host-only)
+                       hostonly_l="no" ;;
+        --persistent-policy)
+                       persistent_policy_l="$2"; shift;;
         --fstab)       use_fstab_l="yes" ;;
-        -h|--help)     usage; exit 1 ;;
+        -h|--help)     long_usage; exit 1 ;;
         -i|--include)  push include_src "$2"
-                       push include_target "$3"
-                       shift 2;;
+                       shift;;
         --bzip2)       compress_l="bzip2";;
         --lzma)        compress_l="lzma";;
         --xz)          compress_l="xz";;
         --no-compress) _no_compress_l="cat";;
         --gzip)        compress_l="gzip";;
-        --list-modules)
-            do_list="yes";
-            ;;
+        --list-modules) do_list="yes";;
         -M|--show-modules)
                        show_modules_l="yes"
                        ;;
         --keep)        keep="yes";;
         --printsize)   printsize="yes";;
-        -*) printf "\nUnknown option: %s\n\n" "$1" >&2; usage; exit 1;;
+        --regenerate-all) regenerate_all="yes";;
+        --noimageifnotneeded) noimageifnotneeded="yes";;
+
+        --) shift; break;;
+
+        *)  # should not even reach this point
+            printf "\n!Unknown option: '%s'\n\n" "$1" >&2; usage; exit 1;;
+    esac
+    shift
+done
+
+# getopt cannot handle multiple arguments, so just handle "-I,--include"
+# the old fashioned way
+
+while (($# > 0)); do
+    case ${1%%=*} in
+        ++include) push include_src "$2"
+                       push include_target "$3"
+                       shift 2;;
         *)
             if ! [[ ${outfile+x} ]]; then
                 outfile=$1
             elif ! [[ ${kernel+x} ]]; then
                 kernel=$1
             else
-                echo "Unknown argument: $1"
+                printf "\nUnknown arguments: %s\n\n" "$*" >&2
                 usage; exit 1;
             fi
             ;;
     esac
     shift
 done
+
+if [[ $regenerate_all == "yes" ]]; then
+    ret=0
+    if [[ $kernel ]]; then
+        printf -- "--regenerate-all cannot be called with a kernel version\n" >&2
+        exit 1
+    fi
+
+    if [[ $outfile ]]; then
+        printf -- "--regenerate-all cannot be called with a image file\n" >&2
+        exit 1
+    fi
+
+    ((len=${#dracut_args[@]}))
+    for ((i=0; i < len; i++)); do
+        [[ ${dracut_args[$i]} == "--regenerate-all" ]] && \
+            unset dracut_args[$i]
+    done
+
+    cd /lib/modules
+    for i in *; do
+        [[ -f $i/modules.builtin ]] || continue
+        dracut --kver="$i" "${dracut_args[@]}"
+        ((ret+=$?))
+    done
+    exit $ret
+elif [[ $kernel ]]; then
+    if ! [[ -d /lib/modules/$kernel ]] && [[ $no_kernel != yes ]]; then
+        printf -- "Kernel version $kernel has no modules in /lib/modules/$kernel\n" >&2
+        exit 1
+    fi
+fi
+
 if ! [[ $kernel ]]; then
     kernel=$(uname -r)
 fi
-[[ $outfile ]] || outfile="/boot/initramfs-$kernel.img"
+
+if ! [[ $outfile ]]; then
+    [[ -f /etc/machine-id ]] && read MACHINE_ID < /etc/machine-id
+
+    if [[ $MACHINE_ID ]] && ( [[ -d /boot/${MACHINE_ID} ]] || [[ -L /boot/${MACHINE_ID} ]] ); then
+        outfile="/boot/${MACHINE_ID}/$kernel/initrd"
+    else
+        outfile="/boot/initramfs-$kernel.img"
+    fi
+fi
 
 for i in /usr/sbin /sbin /usr/bin /bin; do
     rl=$i
     if [ -L "$i" ]; then
         rl=$(readlink -f $i)
     fi
-    NPATH+=":$rl"
+    if [[ "$NPATH" != "*:$rl*" ]] ; then
+        NPATH+=":$rl"
+    fi
 done
 export PATH="${NPATH#:}"
+unset LC_MESSAGES
+unset LC_CTYPE
+export LC_ALL=C
+export LANG=C
 unset NPATH
 unset LD_LIBRARY_PATH
 unset GREP_OPTIONS
 
+export DRACUT_LOG_LEVEL=warning
 [[ $debug ]] && {
+    export DRACUT_LOG_LEVEL=debug
     export PS4='${BASH_SOURCE}@${LINENO}(${FUNCNAME[0]}): ';
     set -x
 }
@@ -330,24 +546,28 @@ unset GREP_OPTIONS
 
 # if we were not passed a config file, try the default one
 if [[ ! -f $conffile ]]; then
-    [[ $allowlocal ]] && conffile="$dracutbasedir/dracut.conf" || \
+    if [[ $allowlocal ]]; then
+        conffile="$dracutbasedir/dracut.conf"
+    else
         conffile="/etc/dracut.conf"
+    fi
 fi
 
 if [[ ! -d $confdir ]]; then
-    [[ $allowlocal ]] && confdir="$dracutbasedir/dracut.conf.d" || \
+    if [[ $allowlocal ]]; then
+        confdir="$dracutbasedir/dracut.conf.d"
+    else
         confdir="/etc/dracut.conf.d"
+    fi
 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
+for f in $(dropindirs_sort ".conf" "$confdir" "$dracutbasedir/dracut.conf.d"); do
+    [[ -e $f ]] && . "$f"
+done
 
 # these optins add to the stuff in the config file
 if (( ${#add_dracutmodules_l[@]} )); then
@@ -430,9 +650,13 @@ stdloglvl=$((stdloglvl + verbosity_mod_l))
 
 [[ $drivers_dir_l ]] && drivers_dir=$drivers_dir_l
 [[ $do_strip_l ]] && do_strip=$do_strip_l
+[[ $do_strip ]] || do_strip=yes
+[[ $do_hardlink_l ]] && do_hardlink=$do_hardlink_l
+[[ $do_hardlink ]] || do_hardlink=yes
 [[ $prefix_l ]] && prefix=$prefix_l
 [[ $prefix = "/" ]] && unset prefix
 [[ $hostonly_l ]] && hostonly=$hostonly_l
+[[ $persistent_policy_l ]] && persistent_policy=$persistent_policy_l
 [[ $use_fstab_l ]] && use_fstab=$use_fstab_l
 [[ $mdadmconf_l ]] && mdadmconf=$mdadmconf_l
 [[ $lvmconf_l ]] && lvmconf=$lvmconf_l
@@ -440,10 +664,12 @@ stdloglvl=$((stdloglvl + verbosity_mod_l))
 [[ $fw_dir ]] || fw_dir="/lib/firmware/updates /lib/firmware"
 [[ $tmpdir_l ]] && tmpdir="$tmpdir_l"
 [[ $tmpdir ]] || tmpdir=/var/tmp
-[[ $do_strip ]] || do_strip=no
 [[ $compress_l ]] && compress=$compress_l
 [[ $show_modules_l ]] && show_modules=$show_modules_l
 [[ $nofscks_l ]] && nofscks="yes"
+[[ $ro_mnt_l ]] && ro_mnt="yes"
+[[ $early_microcode_l ]] && early_microcode=$early_microcode_l
+[[ $early_microcode ]] || early_microcode=no
 # eliminate IFS hackery when messing with fw_dir
 fw_dir=${fw_dir//:/ }
 
@@ -453,8 +679,7 @@ case $compress in
     bzip2) compress="bzip2 -9";;
     lzma)  compress="lzma -9";;
     xz)    compress="xz --check=crc32 --lzma2=dict=1MiB";;
-    gzip)  command -v pigz > /dev/null 2>&1 && compress="pigz -9" || \
-                                         compress="gzip -9";;
+    gzip)  compress="gzip -9"; command -v pigz > /dev/null 2>&1 && compress="pigz -9";;
 esac
 if [[ $_no_compress_l = "cat" ]]; then
     compress="cat"
@@ -463,23 +688,61 @@ fi
 [[ $hostonly = yes ]] && hostonly="-h"
 [[ $hostonly != "-h" ]] && unset hostonly
 
+readonly TMPDIR="$tmpdir"
+readonly initdir="$(mktemp --tmpdir="$TMPDIR/" -d -t initramfs.XXXXXX)"
+[ -d "$initdir" ] || {
+    printf "%s\n" "dracut: mktemp --tmpdir=\"$TMPDIR/\" -d -t initramfs.XXXXXX failed." >&2
+    exit 1
+}
+
+if [[ $early_microcode = yes ]]; then
+    readonly microcode_dir="$(mktemp --tmpdir="$TMPDIR/" -d -t early_microcode.XXXXXX)"
+    [ -d "$microcode_dir" ] || {
+        printf "%s\n" "dracut: mktemp --tmpdir=\"$TMPDIR/\" -d -t early_microcode.XXXXXX failed." >&2
+        exit 1
+    }
+fi
+# clean up after ourselves no matter how we die.
+trap '
+    ret=$?;
+    [[ $outfile ]] && [[ -f $outfile.$$ ]] && rm -f -- "$outfile.$$";
+    [[ $keep ]] && echo "Not removing $initdir." >&2 || { [[ $initdir ]] && rm -rf -- "$initdir"; };
+    [[ $keep ]] && echo "Not removing $microcode_dir." >&2 || { [[ $microcode_dir ]] && rm -Rf -- "$microcode_dir"; };
+    [[ $_dlogdir ]] && rm -Rf -- "$_dlogdir";
+    exit $ret;
+    ' EXIT
+
+# clean up after ourselves no matter how we die.
+trap 'exit 1;' SIGINT
+
+export DRACUT_KERNEL_LAZY="1"
+export DRACUT_RESOLVE_LAZY="1"
+
 if [[ -f $dracutbasedir/dracut-functions.sh ]]; then
     . $dracutbasedir/dracut-functions.sh
 else
-    echo "Cannot find $dracutbasedir/dracut-functions.sh." >&2
-    echo "Are you running from a git checkout?" >&2
-    echo "Try passing -l as an argument to $0" >&2
+    printf "%s\n" "dracut: Cannot find $dracutbasedir/dracut-functions.sh." >&2
+    printf "%s\n" "dracut: Are you running from a git checkout?" >&2
+    printf "%s\n" "dracut: Try passing -l as an argument to $0" >&2
     exit 1
 fi
 
+if ! [[ $print_cmdline ]]; then
+    inst /bin/sh
+    if ! $DRACUT_INSTALL ${initdir+-D "$initdir"} -R "$initdir/bin/sh" &>/dev/null; then
+        unset DRACUT_RESOLVE_LAZY
+        export DRACUT_RESOLVE_DEPS=1
+    fi
+    rm -fr -- ${initdir}/*
+fi
+
 if [[ -f $dracutbasedir/dracut-version.sh ]]; then
     . $dracutbasedir/dracut-version.sh
 fi
 
-# Verify bash version, curret minimum is 3.1
-if (( ${BASH_VERSINFO[0]} < 3 ||
-    ( ${BASH_VERSINFO[0]} == 3 && ${BASH_VERSINFO[1]} < 1 ) )); then
-    dfatal 'You need at least Bash 3.1 to use dracut, sorry.'
+# Verify bash version, current minimum is 3.1
+if (( BASH_VERSINFO[0] < 4 )); then
+    dfatal 'You need at least Bash 4 to use dracut, sorry.'
     exit 1
 fi
 
@@ -508,39 +771,38 @@ if (( ${#omit_drivers_l[@]} )); then
 fi
 omit_drivers=${omit_drivers/-/_}
 
+if (( ${#kernel_cmdline_l[@]} )); then
+    while pop kernel_cmdline_l val; do
+        kernel_cmdline+=" $val "
+    done
+fi
+
 omit_drivers_corrected=""
 for d in $omit_drivers; do
-    strstr " $drivers $add_drivers " " $d " && continue
+    [[ " $drivers $add_drivers " == *\ $d\ * ]] && continue
     omit_drivers_corrected+="$d|"
 done
 omit_drivers="${omit_drivers_corrected%|}"
 unset omit_drivers_corrected
 
-
-ddebug "Executing $0 $dracut_args"
+# prepare args for logging
+for ((i=0; i < ${#dracut_args[@]}; i++)); do
+    [[ "${dracut_args[$i]}" == *\ * ]] && \
+        dracut_args[$i]="\"${dracut_args[$i]}\""
+        #" keep vim happy
+done
+dinfo "Executing: $0 ${dracut_args[@]}"
 
 [[ $do_list = yes ]] && {
     for mod in $dracutbasedir/modules.d/*; do
         [[ -d $mod ]] || continue;
         [[ -e $mod/install || -e $mod/installkernel || \
             -e $mod/module-setup.sh ]] || continue
-        echo ${mod##*/??}
+        printf "%s\n" "${mod##*/??}"
     done
     exit 0
 }
 
-# Detect lib paths
-if ! [[ $libdirs ]] ; then
-    if strstr "$(ldd /bin/sh)" "/lib64/" &>/dev/null \
-        && [[ -d /lib64 ]]; then
-        libdirs+=" /lib64"
-        [[ -d /usr/lib64 ]] && libdirs+=" /usr/lib64"
-    else
-        libdirs+=" /lib"
-        [[ -d /usr/lib ]] && libdirs+=" /usr/lib"
-    fi
-fi
-
 # This is kinda legacy -- eventually it should go away.
 case $dracutmodules in
     ""|auto) dracutmodules="all" ;;
@@ -548,22 +810,13 @@ esac
 
 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
-        dfatal 'To use --kmoddir option module-init-tools >= 3.7 is required.'
-        exit 1
-    fi
-    srcmods="$drivers_dir"
-}
-export srcmods
-
-[[ -f $srcmods/modules.dep ]] || {
-    dfatal "$srcmods/modules.dep is missing. Did you run depmod?"
-    exit 1
-}
+if [[ -d $srcmods ]]; then
+    [[ -f $srcmods/modules.dep ]] || {
+      dwarn "$srcmods/modules.dep is missing. Did you run depmod?"
+    }
+fi
 
-if [[ -f $outfile && ! $force ]]; then
+if [[ -f $outfile && ! $force && ! $print_cmdline ]]; then
     dfatal "Will not override existing initramfs ($outfile) without --force"
     exit 1
 fi
@@ -572,94 +825,155 @@ outdir=${outfile%/*}
 [[ $outdir ]] || outdir="/"
 
 if [[ ! -d "$outdir" ]]; then
-    dfatal "Can't write $outfile: Directory $outdir does not exist."
+    dfatal "Can't write to $outdir: Directory $outdir does not exist or is not accessible."
     exit 1
 elif [[ ! -w "$outdir" ]]; then
-    dfatal "No permission to write $outdir."
+    dfatal "No permission to write to $outdir."
     exit 1
 elif [[ -f "$outfile" && ! -w "$outfile" ]]; then
     dfatal "No permission to write $outfile."
     exit 1
 fi
 
-readonly TMPDIR="$tmpdir"
-readonly initdir=$(mktemp --tmpdir="$TMPDIR/" -d -t initramfs.XXXXXX)
-[ -d "$initdir" ] || {
-    dfatal "mktemp failed."
-    exit 1
-}
-
-# clean up after ourselves no matter how we die.
-trap 'ret=$?;[[ $keep ]] && echo "Not removing $initdir." >&2 || rm -rf "$initdir";exit $ret;' EXIT
-# clean up after ourselves no matter how we die.
-trap 'exit 1;' SIGINT
-
 # Need to be able to have non-root users read stuff (rpcbind etc)
 chmod 755 "$initdir"
 
+if [[ $hostonly ]]; then
+    for i in /sys /proc /run /dev; do
+        if ! findmnt --target "$i" &>/dev/null; then
+            dwarning "Turning off host-only mode: '$i' is not mounted!"
+            unset hostonly
+        fi
+    done
+fi
+
+declare -A host_fs_types
+
 for line in "${fstab_lines[@]}"; do
     set -- $line
     #dev mp fs fsopts
     push host_devs "$1"
-    push host_fs_types "$1|$3"
+    host_fs_types["$1"]="$3"
 done
 
 for f in $add_fstab; do
-    [ -e $f ] || continue
+    [[ -e $f ]] || continue
     while read dev rest; do
-        push host_devs $dev
-    done < $f
+        push host_devs "$dev"
+    done < "$f"
+done
+
+for dev in $add_device; do
+    push host_devs "$dev"
 done
 
+if (( ${#add_device_l[@]} )); then
+    while pop add_device_l val; do
+        add_device+=" $val "
+        push host_devs "$val"
+    done
+fi
+
 if [[ $hostonly ]]; then
     # in hostonly mode, determine all devices, which have to be accessed
     # and examine them for filesystem types
 
-    push host_mp \
+    for mp in \
         "/" \
         "/etc" \
+        "/bin" \
+        "/sbin" \
+        "/lib" \
+        "/lib64" \
         "/usr" \
         "/usr/bin" \
         "/usr/sbin" \
         "/usr/lib" \
         "/usr/lib64" \
-        "/boot"
-
-    for mp in "${host_mp[@]}"; do
+        "/boot";
+    do
+        mp=$(readlink -f "$mp")
         mountpoint "$mp" >/dev/null 2>&1 || continue
-        push host_devs $(readlink -f "/dev/block/$(find_block_device "$mp")")
+        _dev=$(find_block_device "$mp")
+        _bdev=$(readlink -f "/dev/block/$_dev")
+        [[ -b $_bdev ]] && _dev=$_bdev
+        push host_devs $_dev
+        [[ "$_mp" == "/" ]] && root_dev="$_dev"
+        push host_devs "$_dev"
     done
+
+    if [[ -f /proc/swaps ]] && [[ -f /etc/fstab ]]; then
+        while read dev type rest; do
+            [[ -b $dev ]] || continue
+            [[ "$type" == "partition" ]] || continue
+
+            while read _d _m _t _o _r; do
+                [[ "$_d" == \#* ]] && continue
+                [[ $_d ]] || continue
+                [[ $_t != "swap" ]] && continue
+                [[ $_m != "swap" ]] && [[ $_m != "none" ]] && continue
+                [[ "$_o" == *noauto* ]] && continue
+                [[ "$_d" == UUID\=* ]] && _d="/dev/disk/by-uuid/${_d#UUID=}"
+                [[ "$_d" == LABEL\=* ]] && _d="/dev/disk/by-label/$_d#LABEL=}"
+                [[ "$_d" -ef "$dev" ]] || continue
+
+                if [[ -f /etc/crypttab ]]; then
+                    while read _mapper _a _p _o; do
+                        [[ $_mapper = \#* ]] && continue
+                        [[ "$_d" -ef /dev/mapper/"$_mapper" ]] || continue
+                        [[ "$_o" ]] || _o="$_p"
+                        # skip mkswap swap
+                        [[ $_o == *swap* ]] && continue 2
+                    done < /etc/crypttab
+                fi
+
+                push host_devs "$(readlink -f "$dev")"
+                break
+            done < /etc/fstab
+        done < /proc/swaps
+    fi
 fi
 
-_get_fs_type() (
+_get_fs_type() {
     [[ $1 ]] || return
-    if [[ -b $1 ]] && get_fs_env $1; then
-        echo "$(readlink -f $1)|$ID_FS_TYPE"
+    if [[ -b /dev/block/$1 ]] && ID_FS_TYPE=$(get_fs_env "/dev/block/$1"); then
+        host_fs_types["$(readlink -f "/dev/block/$1")"]="$ID_FS_TYPE"
         return 1
     fi
-    if [[ -b /dev/block/$1 ]] && get_fs_env /dev/block/$1; then
-        echo "$(readlink -f /dev/block/$1)|$ID_FS_TYPE"
+    if [[ -b $1 ]] && ID_FS_TYPE=$(get_fs_env "$1"); then
+        host_fs_types["$(readlink -f "$1")"]="$ID_FS_TYPE"
         return 1
     fi
-    if fstype=$(find_dev_fstype $1); then
-        echo "$1|$fstype"
+    if fstype=$(find_dev_fstype "$1"); then
+        host_fs_types["$1"]="$fstype"
         return 1
     fi
     return 1
-)
-
-for dev in "${host_devs[@]}"; do
-    unset fs_type
-    for fstype in $(_get_fs_type $dev) \
-        $(check_block_and_slaves _get_fs_type $(get_maj_min $dev)); do
-        if ! strstr " ${host_fs_types[*]} " " $fstype ";then
-            push host_fs_types "$fstype"
-        fi
-    done
+}
+
+for dev in ${host_devs[@]}; do
+    _get_fs_type "$dev"
+    check_block_and_slaves_all _get_fs_type "$(get_maj_min "$dev")"
+done
+
+for dev in "${!host_fs_types[@]}"; do
+    [[ ${host_fs_types[$dev]} = "reiserfs" ]] || [[ ${host_fs_types[$dev]} = "xfs" ]] || continue
+    rootopts=$(find_dev_fsopts "$dev")
+    if [[ ${host_fs_types[$dev]} = "reiserfs" ]]; then
+        journaldev=$(fs_get_option $rootopts "jdev")
+    elif [[ ${host_fs_types[$dev]} = "xfs" ]]; then
+        journaldev=$(fs_get_option $rootopts "logdev")
+    fi
+    if [[ $journaldev ]]; then
+        dev="$(readlink -f "$dev")"
+        push host_devs "$dev"
+        _get_fs_type "$dev"
+        check_block_and_slaves_all _get_fs_type "$(get_maj_min "$dev")"
+    fi
 done
 
 [[ -d $udevdir ]] \
-    || udevdir=$(pkg-config udev --variable=udevdir 2>/dev/null)
+    || udevdir="$(pkg-config udev --variable=udevdir 2>/dev/null)"
 if ! [[ -d "$udevdir" ]]; then
     [[ -d /lib/udev ]] && udevdir=/lib/udev
     [[ -d /usr/lib/udev ]] && udevdir=/usr/lib/udev
@@ -667,22 +981,50 @@ fi
 
 [[ -d $systemdutildir ]] \
     || systemdutildir=$(pkg-config systemd --variable=systemdutildir 2>/dev/null)
-[[ -d $systemdsystemunitdir ]] \
-    || systemdsystemunitdir=$(pkg-config systemd --variable=systemdsystemunitdir 2>/dev/null)
 
 if ! [[ -d "$systemdutildir" ]]; then
     [[ -d /lib/systemd ]] && systemdutildir=/lib/systemd
     [[ -d /usr/lib/systemd ]] && systemdutildir=/usr/lib/systemd
 fi
+
+[[ -d $systemdsystemunitdir ]] \
+    || systemdsystemunitdir=$(pkg-config systemd --variable=systemdsystemunitdir 2>/dev/null)
+
 [[ -d "$systemdsystemunitdir" ]] || systemdsystemunitdir=${systemdutildir}/system
 
-export initdir dracutbasedir dracutmodules drivers \
+[[ -d $systemdsystemconfdir ]] \
+    || systemdsystemconfdir=$(pkg-config systemd --variable=systemdsystemconfdir 2>/dev/null)
+
+[[ -d "$systemdsystemconfdir" ]] || systemdsystemconfdir=/etc/systemd/system
+
+export initdir dracutbasedir dracutmodules \
     fw_dir drivers_dir debug no_kernel kernel_only \
-    add_drivers omit_drivers mdadmconf lvmconf filesystems \
-    use_fstab fstab_lines libdirs fscks nofscks \
+    omit_drivers mdadmconf lvmconf root_dev \
+    use_fstab fstab_lines libdirs fscks nofscks ro_mnt \
     stdloglvl sysloglvl fileloglvl kmsgloglvl logfile \
     debug host_fs_types host_devs sshkey add_fstab \
-    DRACUT_VERSION udevdir systemdutildir systemdsystemunitdir
+    DRACUT_VERSION udevdir prefix filesystems drivers \
+    systemdutildir systemdsystemunitdir systemdsystemconfdir
+
+mods_to_load=""
+# check all our modules to see if they should be sourced.
+# This builds a list of modules that we will install next.
+for_each_module_dir check_module
+for_each_module_dir check_mount
+
+dracut_module_included "fips" && export DRACUT_FIPS_MODE=1
+
+if [[ $print_cmdline ]]; then
+    modules_loaded=" "
+    # source our modules.
+    for moddir in "$dracutbasedir/modules.d"/[0-9][0-9]*; do
+        _d_mod=${moddir##*/}; _d_mod=${_d_mod#[0-9][0-9]}
+        module_cmdline "$_d_mod"
+    done
+    unset moddir
+    printf "\n"
+    exit 0
+fi
 
 # Create some directory structure first
 [[ $prefix ]] && mkdir -m 0755 -p "${initdir}${prefix}"
@@ -692,13 +1034,13 @@ export initdir dracutbasedir dracutmodules drivers \
 
 if [[ $prefix ]]; then
     for d in bin etc lib sbin tmp usr var $libdirs; do
-        strstr "$d" "/" && continue
+        [[ "$d" == */* ]] && continue
         ln -sfn "${prefix#/}/${d#/}" "$initdir/$d"
     done
 fi
 
 if [[ $kernel_only != yes ]]; then
-    for d in usr/bin usr/sbin bin etc lib sbin tmp usr var var/log var/run var/lock $libdirs; do
+    for d in usr/bin usr/sbin bin etc lib sbin tmp usr var $libdirs; do
         [[ -e "${initdir}${prefix}/$d" ]] && continue
         if [ -L "/$d" ]; then
             inst_symlink "/$d" "${prefix}/$d"
@@ -715,8 +1057,9 @@ if [[ $kernel_only != yes ]]; then
         fi
     done
 
-    ln -sfn /run "$initdir/var/run"
-    ln -sfn /run/lock "$initdir/var/lock"
+    ln -sfn ../run "$initdir/var/run"
+    ln -sfn ../run/lock "$initdir/var/lock"
+    ln -sfn ../run/log "$initdir/var/log"
 else
     for d in lib "$libdir"; do
         [[ -e "${initdir}${prefix}/$d" ]] && continue
@@ -734,38 +1077,32 @@ if [[ $kernel_only != yes ]]; then
         mkdir -m 0755 -p ${initdir}/lib/dracut/hooks/$_d
     done
     if [[ "$UID" = "0" ]]; then
-        for i in /dev/kmsg /dev/null /dev/console; do
-            [ -e $i ] || continue
-            cp -a $i $initdir/dev
-        done
+        [ -c ${initdir}/dev/null ] || mknod ${initdir}/dev/null c 1 3
+        [ -c ${initdir}/dev/kmsg ] || mknod ${initdir}/dev/kmsg c 1 11
+        [ -c ${initdir}/dev/console ] || mknod ${initdir}/dev/console c 5 1
     fi
 fi
 
-mkdir -p "$initdir/.kernelmodseen"
-
-mods_to_load=""
-# check all our modules to see if they should be sourced.
-# This builds a list of modules that we will install next.
-for_each_module_dir check_module
-for_each_module_dir check_mount
-
 _isize=0 #initramfs size
 modules_loaded=" "
 # source our modules.
 for moddir in "$dracutbasedir/modules.d"/[0-9][0-9]*; do
     _d_mod=${moddir##*/}; _d_mod=${_d_mod#[0-9][0-9]}
-    if strstr "$mods_to_load" " $_d_mod "; then
-        [[ $show_modules = yes ]] && echo "$_d_mod" || \
+    if [[ "$mods_to_load" == *\ $_d_mod\ * ]]; then
+        if [[ $show_modules = yes ]]; then
+            printf "%s\n" "$_d_mod"
+        else
             dinfo "*** Including module: $_d_mod ***"
-        if [[ $kernel_only = yes ]]; then
-            module_installkernel $_d_mod || {
+        fi
+        if [[ $kernel_only == yes ]]; then
+            module_installkernel "$_d_mod" || {
                 dfatal "installkernel failed in module $_d_mod"
                 exit 1
             }
         else
-            module_install $_d_mod
+            module_install "$_d_mod"
             if [[ $no_kernel != yes ]]; then
-                module_installkernel $_d_mod || {
+                module_installkernel "$_d_mod" || {
                     dfatal "installkernel failed in module $_d_mod"
                     exit 1
                 }
@@ -777,8 +1114,8 @@ for moddir in "$dracutbasedir/modules.d"/[0-9][0-9]*; do
         #print the module install size
         if [ -n "$printsize" ]; then
             _isize_new=$(du -sk ${initdir}|cut -f1)
-            _isize_delta=$(($_isize_new - $_isize))
-            echo "$_d_mod install size: ${_isize_delta}k"
+            _isize_delta=$((_isize_new - _isize))
+            printf "%s\n" "$_d_mod install size: ${_isize_delta}k"
             _isize=$_isize_new
         fi
     fi
@@ -787,18 +1124,70 @@ unset moddir
 
 for i in $modules_loaded; do
     mkdir -p $initdir/lib/dracut
-    echo "$i" >> $initdir/lib/dracut/modules.txt
+    printf "%s\n" "$i" >> $initdir/lib/dracut/modules.txt
 done
 
 dinfo "*** Including modules done ***"
 
 ## final stuff that has to happen
+if [[ $no_kernel != yes ]]; then
 
-# generate module dependencies for the initrd
-if [[ -d $initdir/lib/modules/$kernel ]] && \
-    ! depmod -a -b "$initdir" $kernel; then
-    dfatal "\"depmod -a $kernel\" failed."
-    exit 1
+    if [[ $drivers ]]; then
+        hostonly='' instmods $drivers
+    fi
+
+    if [[ $add_drivers ]]; then
+        hostonly='' instmods -c $add_drivers
+    fi
+    if [[ $filesystems ]]; then
+        hostonly='' instmods -c $filesystems
+    fi
+
+    dinfo "*** Installing kernel module dependencies and firmware ***"
+    dracut_kernel_post
+    dinfo "*** Installing kernel module dependencies and firmware done ***"
+
+    if [[ $noimageifnotneeded == yes ]] && [[ $hostonly ]]; then
+        if [[ ! -f "$initdir/lib/dracut/need-initqueue" ]] && \
+            [[ -f ${initdir}/lib/modules/$kernel/modules.dep && ! -s ${initdir}/lib/modules/$kernel/modules.dep ]]; then
+            for i in ${initdir}/etc/cmdline.d/*.conf; do
+                # We need no initramfs image and do not generate one.
+                [[ $i == "${initdir}/etc/cmdline.d/*.conf" ]] && exit 0
+            done
+        fi
+    fi
+fi
+
+if [[ $kernel_only != yes ]]; then
+    (( ${#install_items[@]} > 0 )) && inst_multiple ${install_items[@]}
+
+    [[ $kernel_cmdline ]] && printf "%s\n" "$kernel_cmdline" >> "${initdir}/etc/cmdline.d/01-default.conf"
+
+    while pop fstab_lines line; do
+        printf "%s\n" "$line 0 0" >> "${initdir}/etc/fstab"
+    done
+
+    for f in $add_fstab; do
+        cat "$f" >> "${initdir}/etc/fstab"
+    done
+
+    if [ -d ${initdir}/$systemdutildir ]; then
+        mkdir -p ${initdir}/etc/conf.d
+        {
+            printf "%s\n" "systemdutildir=\"$systemdutildir\""
+            printf "%s\n" "systemdsystemunitdir=\"$systemdsystemunitdir\""
+            printf "%s\n" "systemdsystemconfdir=\"$systemdsystemconfdir\""
+        } > ${initdir}/etc/conf.d/systemd.conf
+    fi
+
+    if [[ $DRACUT_RESOLVE_LAZY ]] && [[ $DRACUT_INSTALL ]]; then
+        dinfo "*** Resolving executable dependencies ***"
+        find "$initdir" -type f \
+            '(' -perm -0100 -or -perm -0010 -or -perm -0001 ')' \
+            -not -path '*.ko' -print0 \
+        | xargs -r -0 $DRACUT_INSTALL ${initdir+-D "$initdir"} -R ${DRACUT_FIPS_MODE+-H} --
+        dinfo "*** Resolving executable dependencies done***"
+    fi
 fi
 
 while pop include_src src && pop include_target tgt; do
@@ -818,9 +1207,9 @@ while pop include_src src && pop include_target tgt; do
                         mkdir -m 0755 -p "$s"
                         chmod --reference="$i" "$s"
                     fi
-                    cp -a -t "$s" "$i"/*
+                    cp --reflink=auto --sparse=auto -fa -t "$s" "$i"/*
                 else
-                    cp -a -t "$s" "$i"
+                    cp --reflink=auto --sparse=auto -fa -t "$s" "$i"
                 fi
             done
         fi
@@ -828,19 +1217,6 @@ while pop include_src src && pop include_target tgt; do
 done
 
 if [[ $kernel_only != yes ]]; then
-    for item in $install_items; do
-        dracut_install "$item"
-    done
-    unset item
-
-    while pop fstab_lines line; do
-        echo "$line 0 0" >> "${initdir}/etc/fstab"
-    done
-
-    for f in $add_fstab; do
-        cat $f >> "${initdir}/etc/fstab"
-    done
-
     # make sure that library links are correct and up to date
     for f in /etc/ld.so.conf /etc/ld.so.conf.d/*; do
         [[ -f $f ]] && inst_simple "$f"
@@ -854,56 +1230,99 @@ if [[ $kernel_only != yes ]]; then
     fi
 fi
 
-rm -fr "$initdir/.kernelmodseen"
-
+PRELINK_BIN="$(command -v prelink)"
+if [[ $UID = 0 ]] && [[ $PRELINK_BIN ]]; then
+    if [[ $DRACUT_FIPS_MODE ]]; then
+        dinfo "*** Installing prelink files ***"
+        inst_multiple -o prelink /etc/prelink.conf /etc/prelink.conf.d/*.conf /etc/prelink.cache
+    else
+        dinfo "*** Pre-linking files ***"
+        inst_multiple -o prelink /etc/prelink.conf /etc/prelink.conf.d/*.conf
+        chroot "$initdir" "$PRELINK_BIN" -a
+        rm -f -- "$initdir/$PRELINK_BIN"
+        rm -fr -- "$initdir"/etc/prelink.*
+        dinfo "*** Pre-linking files done ***"
+    fi
+fi
 
-if (($maxloglvl >= 5)); then
-    ddebug "Listing sizes of included files:"
-    du -c "$initdir" | sort -n | ddebug
+if [[ $do_hardlink = yes ]] && command -v hardlink >/dev/null; then
+    dinfo "*** Hardlinking files ***"
+    hardlink "$initdir" 2>&1
+    dinfo "*** Hardlinking files done ***"
 fi
 
 # strip binaries
 if [[ $do_strip = yes ]] ; then
-    for p in strip grep find; do
+    for p in strip xargs find; do
         if ! type -P $p >/dev/null; then
-            derror "Could not find '$p'. You should run $0 with '--nostrip'."
+            dinfo "Could not find '$p'. Not stripping the initramfs."
             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|| :
-    done
-fi
+if [[ $do_strip = yes ]] && ! [[ $DRACUT_FIPS_MODE ]]; then
+    dinfo "*** Stripping files ***"
+    find "$initdir" -type f \
+        -executable -not -path '*/lib/modules/*.ko' -print0 \
+        | xargs -r -0 strip -g 2>/dev/null
 
-type hardlink &>/dev/null && {
-    hardlink "$initdir" 2>&1
-}
+    # strip kernel modules, but do not touch signed modules
+    find "$initdir" -type f -path '*/lib/modules/*.ko' -print0 \
+        | while read -r -d $'\0' f; do
+        SIG=$(tail -c 28 "$f")
+        [[ $SIG == '~Module signature appended~' ]] || { printf "%s\000" "$f"; }
+    done | xargs -r -0 strip -g
 
-if strstr "$modules_loaded" " fips " && command -v prelink >/dev/null; then
-    for dir in "$initdir/bin" \
-       "$initdir/sbin" \
-       "$initdir/usr/bin" \
-       "$initdir/usr/sbin"; do
-        [[ -L "$dir" ]] && continue
-        for i in "$dir"/*; do
-            [[ -x $i ]] && prelink -u $i &>/dev/null
+    dinfo "*** Stripping files done ***"
+fi
+if [[ $early_microcode = yes ]]; then
+    dinfo "*** Generating early-microcode cpio image ***"
+    ucode_dir=(amd-ucode intel-ucode)
+    ucode_dest=(AuthenticAMD.bin GenuineIntel.bin)
+    _dest_dir="$microcode_dir/d/kernel/x86/microcode"
+    _dest_idx="0 1"
+    mkdir -p $_dest_dir
+    if [[ $hostonly ]]; then
+        [[ $(get_cpu_vendor) == "AMD" ]] && _dest_idx="0"
+        [[ $(get_cpu_vendor) == "Intel" ]] && _dest_idx="1"
+    fi
+    for idx in $_dest_idx; do
+        _fw=${ucode_dir[$idx]}
+        for _fwdir in $fw_dir; do
+            if [[ -d $_fwdir && -d $_fwdir/$_fw ]]; then
+                _src="*"
+                dinfo "*** Constructing ${ucode_dest[$idx]} ****"
+                if [[ $hostonly ]]; then
+                    _src=$(get_ucode_file)
+                fi
+                cat $_fwdir/$_fw/$_src > $_dest_dir/${ucode_dest[$idx]}
+            fi
         done
     done
+    (cd "$microcode_dir/d"; find . -print0 | cpio --null -o -H newc --quiet >../ucode.cpio)
 fi
 
-if ! ( cd "$initdir"; find . |cpio -R 0:0 -H newc -o --quiet| \
-    $compress > "$outfile"; ); then
-    dfatal "dracut: creation of $outfile failed"
+rm -f -- "$outfile"
+dinfo "*** Creating image file ***"
+if [[ $early_microcode = yes ]]; then
+    # The microcode blob is _before_ the initramfs blob, not after
+    mv $microcode_dir/ucode.cpio $outfile.$$
+fi
+if ! ( umask 077; cd "$initdir"; find . -print0 | cpio --null -R 0:0 -H newc -o --quiet| \
+    $compress >> "$outfile.$$"; ); then
+    dfatal "dracut: creation of $outfile.$$ failed"
     exit 1
 fi
+mv -- "$outfile.$$" "$outfile"
+dinfo "*** Creating image file done ***"
 
-dinfo "Wrote $outfile:"
-dinfo "$(ls -l "$outfile")"
+if (( maxloglvl >= 5 )); then
+    if [[ $allowlocal ]]; then
+       "$dracutbasedir/lsinitrd.sh" "$outfile"| ddebug
+    else
+        lsinitrd "$outfile"| ddebug
+    fi
+fi
 
 exit 0