-#!/bin/bash --norc
+#!/bin/bash -p
#
# Generator script for a dracut initramfs
# Tries to retain some degree of compatibility with the command line
# store for logging
+unset BASH_ENV
+
# Verify bash version, current minimum is 4
if (( BASH_VERSINFO[0] < 4 )); then
printf -- 'You need at least Bash 4 to use dracut, sorry.' >&2
set -o pipefail
usage() {
- [[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut
+ [[ $sysroot_l ]] && dracutsysrootdir="$sysroot_l"
+ [[ $dracutbasedir ]] || dracutbasedir=$dracutsysrootdir/usr/lib/dracut
if [[ -f $dracutbasedir/dracut-version.sh ]]; then
. $dracutbasedir/dracut-version.sh
fi
}
long_usage() {
- [[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut
+ [[ $dracutbasedir ]] || dracutbasedir=$dracutsysrootdir/usr/lib/dracut
if [[ -f $dracutbasedir/dracut-version.sh ]]; then
. $dracutbasedir/dracut-version.sh
fi
--kernel-cmdline [PARAMETERS] Specify default kernel command line parameters
--strip Strip binaries in the initramfs
--nostrip Do not strip binaries in the initramfs
- --prelink Prelink binaries in the initramfs
- --noprelink Do not prelink 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]
from. Default: /etc/dracut.conf.d
--tmpdir [DIR] Temporary directory to be used instead of default
/var/tmp.
+ -r, --sysroot [DIR] Specify sysroot directory to collect files from.
-l, --local Local mode. Use modules from the current working
directory instead of the system-wide installed in
/usr/lib/dracut/modules.d.
-H, --hostonly Host-Only mode: Install only what is needed for
booting the local host instead of a generic host.
-N, --no-hostonly Disables Host-Only mode
+ --hostonly-mode <mode>
+ Specify the hostonly mode to use. <mode> could be
+ one of "sloppy" or "strict". "sloppy" mode is used
+ by default.
+ In "sloppy" hostonly mode, extra drivers and modules
+ will be installed, so minor hardware change won't make
+ the image unbootable (eg. changed keyboard), and the
+ image is still portable among similar hosts.
+ With "strict" mode enabled, anything not necessary
+ for booting the local host in its current state will
+ not be included, and modules may do some extra job
+ to save more space. Minor change of hardware or
+ environment could make the image unbootable.
+ DO NOT use "strict" mode unless you know what you
+ are doing.
--hostonly-cmdline Store kernel command line arguments needed
in the initramfs
--no-hostonly-cmdline Do not store kernel command line arguments needed
rearrange_params()
{
# 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}"
+ newat=()
+ for i in "$@"; do
+ if [[ $i == "-i" ]] || [[ $i == "--include" ]]; then
+ newat+=("++include") # Replace --include by ++include
+ else
+ newat+=("$i")
+ fi
+ done
+ set -- "${newat[@]}" # Set new $@
TEMP=$(unset POSIXLY_CORRECT; getopt \
- -o "a:m:o:d:I:k:c:L:fvqlHhMN" \
+ -o "a:m:o:d:I:k:c:r:L:fvqlHhMN" \
--long kver: \
--long add: \
--long force-add: \
--long conf: \
--long confdir: \
--long tmpdir: \
+ --long sysroot: \
--long stdlog: \
--long compress: \
--long prefix: \
--long kernel-cmdline: \
--long strip \
--long nostrip \
- --long prelink \
- --long noprelink \
--long hardlink \
--long nohardlink \
--long noprefix \
--long host-only \
--long no-hostonly \
--long no-host-only \
+ --long hostonly-mode: \
--long hostonly-cmdline \
--long no-hostonly-cmdline \
--long no-hostonly-default-device \
eval set -- "$TEMP"
rearrange_params "$@"
fi
-
- # clean the temporarily used scratch-pad directory
- rm -rf $scratch_dir
fi
unset PARMS_TO_STORE
-c|--conf) conffile="$2"; PARMS_TO_STORE+=" '$2'"; shift;;
--confdir) confdir="$2"; PARMS_TO_STORE+=" '$2'"; shift;;
--tmpdir) tmpdir_l="$2"; PARMS_TO_STORE+=" '$2'"; shift;;
+ -r|--sysroot) sysroot_l="$2"; PARMS_TO_STORE+=" '$2'"; shift;;
-L|--stdlog) stdloglvl_l="$2"; PARMS_TO_STORE+=" '$2'"; shift;;
--compress) compress_l="$2"; PARMS_TO_STORE+=" '$2'"; shift;;
--prefix) prefix_l="$2"; PARMS_TO_STORE+=" '$2'"; shift;;
early_microcode_l="no";;
--strip) do_strip_l="yes";;
--nostrip) do_strip_l="no";;
- --prelink) do_prelink_l="yes";;
- --noprelink) do_prelink_l="no";;
--hardlink) do_hardlink_l="yes";;
--nohardlink) do_hardlink_l="no";;
--noprefix) prefix_l="/";;
hostonly_l="yes" ;;
-N|--no-hostonly|--no-host-only)
hostonly_l="no" ;;
+ --hostonly-mode)
+ hostonly_mode_l="$2"; PARMS_TO_STORE+=" '$2'"; shift;;
--hostonly-cmdline)
hostonly_cmdline_l="yes" ;;
--hostonly-i18n)
shift
done
+[[ $sysroot_l ]] && dracutsysrootdir="$sysroot_l"
+
if [[ $regenerate_all == "yes" ]]; then
ret=0
if [[ $kernel ]]; then
unset dracut_args[$i]
done
- cd /lib/modules
+ cd $dracutsysrootdir/lib/modules
for i in *; do
[[ -f $i/modules.dep ]] || [[ -f $i/modules.dep.bin ]] || continue
"$dracut_cmd" --kver="$i" "${dracut_args[@]}"
debug=yes
}
-[[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut
+[[ $dracutbasedir ]] || dracutbasedir=$dracutsysrootdir/usr/lib/dracut
# if we were not passed a config file, try the default one
if [[ ! -f $conffile ]]; then
if [[ $allowlocal ]]; then
conffile="$dracutbasedir/dracut.conf"
else
- conffile="/etc/dracut.conf"
+ conffile="$dracutsysrootdir/etc/dracut.conf"
fi
fi
if [[ $allowlocal ]]; then
confdir="$dracutbasedir/dracut.conf.d"
else
- confdir="/etc/dracut.conf.d"
+ confdir="$dracutsysrootdir/etc/dracut.conf.d"
fi
fi
for i in $DRACUT_PATH; do
rl=$i
- if [ -L "$i" ]; then
- rl=$(readlink -f $i)
+ if [ -L "$dracutsysrootdir$i" ]; then
+ rl=$(readlink -f $dracutsysrootdir$i)
fi
if [[ "$NPATH" != *:$rl* ]] ; then
NPATH+=":$rl"
[[ $drivers_dir_l ]] && drivers_dir=$drivers_dir_l
[[ $do_strip_l ]] && do_strip=$do_strip_l
[[ $do_strip ]] || do_strip=yes
-[[ $do_prelink_l ]] && do_prelink=$do_prelink_l
-[[ $do_prelink ]] || do_prelink=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
[[ $hostonly_cmdline_l ]] && hostonly_cmdline=$hostonly_cmdline_l
+[[ $hostonly_mode_l ]] && hostonly_mode=$hostonly_mode_l
[[ "$hostonly" == "yes" ]] && ! [[ $hostonly_cmdline ]] && hostonly_cmdline="yes"
[[ $i18n_install_all_l ]] && i18n_install_all=$i18n_install_all_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
-[[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut
-[[ $fw_dir ]] || fw_dir="/lib/firmware/updates:/lib/firmware:/lib/firmware/$kernel"
+[[ $dracutbasedir ]] || dracutbasedir=$dracutsysrootdir/usr/lib/dracut
+[[ $fw_dir ]] || fw_dir="$dracutsysrootdir/lib/firmware/updates:$dracutsysrootdir/lib/firmware:$dracutsysrootdir/lib/firmware/$kernel"
[[ $tmpdir_l ]] && tmpdir="$tmpdir_l"
-[[ $tmpdir ]] || tmpdir=/var/tmp
+[[ $tmpdir ]] || tmpdir=$dracutsysrootdir/var/tmp
[[ $INITRD_COMPRESS ]] && compress=$INITRD_COMPRESS
[[ $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
+[[ $early_microcode ]] || early_microcode=yes
[[ $logfile_l ]] && logfile="$logfile_l"
[[ $reproducible_l ]] && reproducible="$reproducible_l"
[[ $loginstall_l ]] && loginstall="$loginstall_l"
if ! [[ $outfile ]]; then
if [[ $machine_id != "no" ]]; then
- [[ -f /etc/machine-id ]] && read MACHINE_ID < /etc/machine-id
+ [[ -f $dracutsysrootdir/etc/machine-id ]] && read MACHINE_ID < $dracutsysrootdir/etc/machine-id
fi
if [[ $uefi == "yes" ]]; then
- BUILD_ID=$(cat /etc/os-release /usr/lib/os-release \
+ if [[ -n "$uefi_secureboot_key" && -z "$uefi_secureboot_cert" ]] || [[ -z $uefi_secureboot_key && -n $uefi_secureboot_cert ]]; then
+ dfatal "Need 'uefi_secureboot_key' and 'uefi_secureboot_cert' both to be set."
+ exit 1
+ fi
+
+ if [[ -n "$uefi_secureboot_key" && -n "$uefi_secureboot_cert" ]] && !command -v sbsign &>/dev/null; then
+ dfatal "Need 'sbsign' to create a signed UEFI executable"
+ exit 1
+ fi
+
+ BUILD_ID=$(cat $dracutsysrootdir/etc/os-release $dracutsysrootdir/usr/lib/os-release \
| while read -r line || [[ $line ]]; do \
[[ $line =~ BUILD_ID\=* ]] && eval "$line" && echo "$BUILD_ID" && break; \
done)
- if [[ -d /efi ]] && mountpoint -q /efi; then
- efidir=/efi
+ if [[ -z $dracutsysrootdir ]]; then
+ if [[ -d /efi ]] && mountpoint -q /efi; then
+ efidir=/efi/EFI
+ else
+ efidir=/boot/EFI
+ if [[ -d $dracutsysrootdir/boot/efi/EFI ]]; then
+ efidir=/boot/efi/EFI
+ fi
+ fi
else
efidir=/boot/EFI
- if [[ -d /boot/efi/EFI ]] && mountpoint -q /boot/efi; then
+ if [[ -d $dracutsysrootdir/boot/efi/EFI ]]; then
efidir=/boot/efi/EFI
fi
fi
- mkdir -p "$efidir/Linux"
- outfile="$efidir/Linux/linux-$kernel${MACHINE_ID:+-${MACHINE_ID}}${BUILD_ID:+-${BUILD_ID}}.efi"
+ mkdir -p "$dracutsysrootdir$efidir/Linux"
+ outfile="$dracutsysrootdir$efidir/Linux/linux-$kernel${MACHINE_ID:+-${MACHINE_ID}}${BUILD_ID:+-${BUILD_ID}}.efi"
else
- if [[ -e "/boot/vmlinuz-$kernel" ]]; then
+ if [[ -e "$dracutsysrootdir/boot/vmlinuz-$kernel" ]]; then
outfile="/boot/initramfs-$kernel.img"
- elif [[ $MACHINE_ID ]] && ( [[ -d /boot/${MACHINE_ID} ]] || [[ -L /boot/${MACHINE_ID} ]] ); then
- outfile="/boot/${MACHINE_ID}/$kernel/initrd"
+ elif [[ $MACHINE_ID ]] && ( [[ -d $dracutsysrootdir/boot/${MACHINE_ID} ]] || [[ -L $dracutsysrootdir/boot/${MACHINE_ID} ]] ); then
+ outfile="$dracutsysrootdir/boot/${MACHINE_ID}/$kernel/initrd"
else
- outfile="/boot/initramfs-$kernel.img"
+ outfile="$dracutsysrootdir/boot/initramfs-$kernel.img"
fi
fi
fi
fi
# handle compression options.
-if [[ $_no_compress_l = "cat" ]]; then
- compress="cat"
+DRACUT_COMPRESS_BZIP2=${DRACUT_COMPRESS_BZIP2:-bzip2}
+DRACUT_COMPRESS_LBZIP2=${DRACUT_COMPRESS_LBZIP2:-lbzip2}
+DRACUT_COMPRESS_LZMA=${DRACUT_COMPRESS_LZMA:-lzma}
+DRACUT_COMPRESS_XZ=${DRACUT_COMPRESS_XZ:-xz}
+DRACUT_COMPRESS_GZIP=${DRACUT_COMPRESS_GZIP:-gzip}
+DRACUT_COMPRESS_PIGZ=${DRACUT_COMPRESS_PIGZ:-pigz}
+DRACUT_COMPRESS_LZOP=${DRACUT_COMPRESS_LZOP:-lzop}
+DRACUT_COMPRESS_ZSTD=${DRACUT_COMPRESS_ZSTD:-zstd}
+DRACUT_COMPRESS_LZ4=${DRACUT_COMPRESS_LZ4:-lz4}
+DRACUT_COMPRESS_CAT=${DRACUT_COMPRESS_CAT:-cat}
+
+if [[ $_no_compress_l = "$DRACUT_COMPRESS_CAT" ]]; then
+ compress="$DRACUT_COMPRESS_CAT"
fi
if ! [[ $compress ]]; then
# check all known compressors, if none specified
- for i in pigz gzip lz4 lzop zstd lzma xz lbzip2 bzip2 cat; do
+ for i in $DRACUT_COMPRESS_PIGZ $DRACUT_COMPRESS_GZIP $DRACUT_COMPRESS_LZ4 $DRACUT_COMPRESS_LZOP $ $DRACUT_COMPRESS_ZSTD $DRACUT_COMPRESS_LZMA $DRACUT_COMPRESS_XZ $DRACUT_COMPRESS_LBZIP2 $OMPRESS_BZIP2 $DRACUT_COMPRESS_CAT; do
command -v "$i" &>/dev/null || continue
compress="$i"
break
# choose the right arguments for the compressor
case $compress in
bzip2|lbzip2)
- if [[ "$compress" = lbzip2 ]] || command -v lbzip2 &>/dev/null; then
- compress="lbzip2 -9"
+ if [[ "$compress" = lbzip2 ]] || command -v $DRACUT_COMPRESS_LBZIP2 &>/dev/null; then
+ compress="$DRACUT_COMPRESS_LBZIP2 -9"
else
- compress="bzip2 -9"
+ compress="$DRACUT_COMPRESS_BZIP2 -9"
fi
;;
lzma)
- compress="lzma -9 -T0"
+ compress="$DRACUT_COMPRESS_LZMA -9 -T0"
;;
xz)
- compress="xz --check=crc32 --lzma2=dict=1MiB -T0"
+ compress="$DRACUT_COMPRESS_XZ --check=crc32 --lzma2=dict=1MiB -T0"
;;
gzip|pigz)
- if [[ "$compress" = pigz ]] || command -v pigz &>/dev/null; then
- compress="pigz -9 -n -T -R"
- elif command -v gzip &>/dev/null && gzip --help 2>&1 | grep -q rsyncable; then
- compress="gzip -n -9 --rsyncable"
+ if [[ "$compress" = pigz ]] || command -v $DRACUT_COMPRESS_PIGZ &>/dev/null; then
+ compress="$DRACUT_COMPRESS_PIGZ -9 -n -T -R"
+ elif command -v gzip &>/dev/null && $DRACUT_COMPRESS_GZIP --help 2>&1 | grep -q rsyncable; then
+ compress="$DRACUT_COMPRESS_GZIP -n -9 --rsyncable"
else
- compress="gzip -n -9"
+ compress="$DRACUT_COMPRESS_GZIP -n -9"
fi
;;
lzo|lzop)
- compress="lzop -9"
+ compress="$DRACUT_COMPRESS_LZOP -9"
;;
lz4)
- compress="lz4 -l -9"
+ compress="$DRACUT_COMPRESS_LZ4 -l -9"
;;
zstd)
- compress="zstd -15 -q -T0"
+ compress="$DRACUT_COMPRESS_ZSTD -15 -q -T0"
;;
esac
[[ $hostonly = yes ]] && hostonly="-h"
[[ $hostonly != "-h" ]] && unset hostonly
+case $hostonly_mode in
+ '')
+ [[ $hostonly ]] && hostonly_mode="sloppy" ;;
+ sloppy|strict)
+ if [[ ! $hostonly ]]; then
+ unset hostonly_mode
+ fi
+ ;;
+ *)
+ printf "%s\n" "dracut: Invalid hostonly mode '$hostonly_mode'." >&2
+ exit 1
+esac
+
[[ $reproducible == yes ]] && DRACUT_REPRODUCIBLE=1
readonly TMPDIR="$(realpath -e "$tmpdir")"
mkdir "$early_cpio_dir"
fi
-export DRACUT_RESOLVE_LAZY="1"
+[[ -n "$dracutsysrootdir" ]] || export DRACUT_RESOLVE_LAZY="1"
if [[ $print_cmdline ]]; then
stdloglvl=0
fi
if ! [[ $print_cmdline ]]; then
- inst /bin/sh
- if ! $DRACUT_INSTALL ${initdir:+-D "$initdir"} -R "$initdir/bin/sh" &>/dev/null; then
+ inst $DRACUT_TESTBIN
+ if ! $DRACUT_INSTALL ${initdir:+-D "$initdir"} ${dracutsysrootdir:+-r "$dracutsysrootdir"} -R "$DRACUT_TESTBIN" &>/dev/null; then
unset DRACUT_RESOLVE_LAZY
export DRACUT_RESOLVE_DEPS=1
fi
abs_outfile=$(readlink -f "$outfile") && outfile="$abs_outfile"
+
+[[ -d $dracutsysrootdir$systemdutildir ]] \
+ || systemdutildir=$(pkg-config systemd --variable=systemdutildir 2>/dev/null)
+
+if ! [[ -d "$dracutsysrootdir$systemdutildir" ]]; then
+ [[ -e $dracutsysrootdir/lib/systemd/systemd-udevd ]] && systemdutildir=/lib/systemd
+ [[ -e $dracutsysrootdir/usr/lib/systemd/systemd-udevd ]] && systemdutildir=/usr/lib/systemd
+fi
+
+
if [[ $no_kernel != yes ]] && [[ -d $srcmods ]]; then
if ! [[ -f $srcmods/modules.dep ]]; then
if [[ -n "$(find "$srcmods" -name '*.ko*')" ]]; then
exit 1
fi
unset EFI_MACHINE_TYPE_NAME
- case $(arch) in
+ case $(uname -m) in
x86_64)
EFI_MACHINE_TYPE_NAME=x64;;
ia32)
EFI_MACHINE_TYPE_NAME=ia32;;
*)
- dfatal "Architecture '$(arch)' not supported to create a UEFI executable"
+ dfatal "Architecture '$(uname -m)' not supported to create a UEFI executable"
exit 1
;;
esac
if ! [[ -s $uefi_stub ]]; then
for uefi_stub in \
- "${systemdutildir}/boot/efi/linux${EFI_MACHINE_TYPE_NAME}.efi.stub" \
- "/usr/lib/gummiboot/linux${EFI_MACHINE_TYPE_NAME}.efi.stub"; do
+ $dracutsysrootdir"${systemdutildir}/boot/efi/linux${EFI_MACHINE_TYPE_NAME}.efi.stub" \
+ "$dracutsysrootdir/usr/lib/gummiboot/linux${EFI_MACHINE_TYPE_NAME}.efi.stub"; do
[[ -s $uefi_stub ]] || continue
break
done
fi
if ! [[ $kernel_image ]]; then
- for kernel_image in "/lib/modules/$kernel/vmlinuz" "/boot/vmlinuz-$kernel"; do
+ for kernel_image in "$dracutsysrootdir/lib/modules/$kernel/vmlinuz" "$dracutsysrootdir/boot/vmlinuz-$kernel"; do
[[ -s "$kernel_image" ]] || continue
break
done
"/usr/lib64" \
"/boot" \
"/boot/efi" \
+ "/boot/zipl" \
;
do
- mp=$(readlink -f "$mp")
+ mp=$(readlink -f "$dracutsysrootdir$mp")
mountpoint "$mp" >/dev/null 2>&1 || continue
_dev=$(find_block_device "$mp")
_bdev=$(readlink -f "/dev/block/$_dev")
fi
done
- if [[ -f /proc/swaps ]] && [[ -f /etc/fstab ]]; then
+ # TODO - with sysroot, /proc/swaps is not relevant
+ if [[ -f /proc/swaps ]] && [[ -f $dracutsysrootdir/etc/fstab ]]; then
while read dev type rest || [ -n "$dev" ]; do
[[ -b $dev ]] || continue
[[ "$type" == "partition" ]] || continue
_d=$(expand_persistent_dev "$_d")
[[ "$_d" -ef "$dev" ]] || continue
- if [[ -f /etc/crypttab ]]; then
+ if [[ -f $dracutsysrootdir/etc/crypttab ]]; then
while read _mapper _a _p _o || [ -n "$_mapper" ]; do
[[ $_mapper = \#* ]] && continue
[[ "$_d" -ef /dev/mapper/"$_mapper" ]] || continue
[[ "$_p" == /* ]] && [[ -f $_p ]] && continue 2
# skip mkswap swap
[[ $_o == *swap* ]] && continue 2
- done < /etc/crypttab
+ done < $dracutsysrootdir/etc/crypttab
fi
_dev="$(readlink -f "$dev")"
push_host_devs "$_dev"
swap_devs+=("$_dev")
break
- done < /etc/fstab
+ done < $dracutsysrootdir/etc/fstab
done < /proc/swaps
fi
# collect all "x-initrd.mount" entries from /etc/fstab
- if [[ -f /etc/fstab ]]; then
+ if [[ -f $dracutsysrootdir/etc/fstab ]]; then
while read _d _m _t _o _r || [ -n "$_d" ]; do
[[ "$_d" == \#* ]] && continue
[[ $_d ]] || continue
push_host_devs "$_dev"
if [[ "$_t" == btrfs ]]; then
- for i in $(find_btrfs_devs "$_m"); do
+ for i in $(btrfs_devs "$_m"); do
push_host_devs "$i"
done
fi
- done < /etc/fstab
+ done < $dracutsysrootdir/etc/fstab
fi
fi
fi
done
-[[ -d $udevdir ]] \
+[[ -d $dracutsysrootdir$udevdir ]] \
|| udevdir="$(pkg-config udev --variable=udevdir 2>/dev/null)"
-if ! [[ -d "$udevdir" ]]; then
- [[ ! -h /lib ]] && [[ -d /lib/udev ]] && udevdir=/lib/udev
- [[ -d /usr/lib/udev ]] && udevdir=/usr/lib/udev
+if ! [[ -d "$dracutsysrootdir$udevdir" ]]; then
+ [[ -e $dracutsysrootdir/lib/udev/ata_id ]] && udevdir=/lib/udev
+ [[ -e $dracutsysrootdir/usr/lib/udev/ata_id ]] && udevdir=/usr/lib/udev
fi
-[[ -d $systemdutildir ]] \
- || systemdutildir=$(pkg-config systemd --variable=systemdutildir 2>/dev/null)
-
-if ! [[ -d "$systemdutildir" ]]; then
- [[ ! -h /lib ]] && [[ -d /lib/systemd ]] && systemdutildir=/lib/systemd
- [[ -d /usr/lib/systemd ]] && systemdutildir=/usr/lib/systemd
-fi
-
-[[ -d $systemdsystemunitdir ]] \
+[[ -d $dracutsysrootdir$systemdsystemunitdir ]] \
|| systemdsystemunitdir=$(pkg-config systemd --variable=systemdsystemunitdir 2>/dev/null)
-[[ -d "$systemdsystemunitdir" ]] || systemdsystemunitdir=${systemdutildir}/system
+[[ -d "$dracutsysrootdir$systemdsystemunitdir" ]] || systemdsystemunitdir=${systemdutildir}/system
-[[ -d $systemdsystemconfdir ]] \
+[[ -d $dracutsysrootdir$systemdsystemconfdir ]] \
|| systemdsystemconfdir=$(pkg-config systemd --variable=systemdsystemconfdir 2>/dev/null)
-[[ -d "$systemdsystemconfdir" ]] || systemdsystemconfdir=/etc/systemd/system
+[[ -d "$dracutsysrootdir$systemdsystemconfdir" ]] || systemdsystemconfdir=/etc/systemd/system
-[[ -d $tmpfilesdir ]] \
+[[ -d $dracutsysrootdir$tmpfilesdir ]] \
|| tmpfilesdir=$(pkg-config systemd --variable=tmpfilesdir 2>/dev/null)
-if ! [[ -d "$tmpfilesdir" ]]; then
- [[ -d /lib/tmpfiles.d ]] && tmpfilesdir=/lib/tmpfiles.d
- [[ -d /usr/lib/tmpfiles.d ]] && tmpfilesdir=/usr/lib/tmpfiles.d
+if ! [[ -d "$dracutsysrootdir$tmpfilesdir" ]]; then
+ [[ -d $dracutsysrootdir/lib/tmpfiles.d ]] && tmpfilesdir=/lib/tmpfiles.d
+ [[ -d $dracutsysrootdir/usr/lib/tmpfiles.d ]] && tmpfilesdir=/usr/lib/tmpfiles.d
fi
export initdir dracutbasedir \
for moddir in "$dracutbasedir/modules.d"/[0-9][0-9]*; do
_d_mod=${moddir##*/}; _d_mod=${_d_mod#[0-9][0-9]}
[[ ${_mods_to_print[$_d_mod]} ]] || continue
- module_cmdline "$_d_mod"
+ module_cmdline "$_d_mod" "$moddir"
done
unset moddir
}
# Create some directory structure first
[[ $prefix ]] && mkdir -m 0755 -p "${initdir}${prefix}"
-[[ -h /lib ]] || mkdir -m 0755 -p "${initdir}${prefix}/lib"
+[[ -h $dracutsysrootdir/lib ]] || mkdir -m 0755 -p "${initdir}${prefix}/lib"
[[ $prefix ]] && ln -sfn "${prefix#/}/lib" "$initdir/lib"
if [[ $prefix ]]; then
dinfo "*** Including module: $_d_mod ***"
fi
if [[ $kernel_only == yes ]]; then
- module_installkernel "$_d_mod" || {
+ module_installkernel "$_d_mod" "$moddir" || {
dfatal "installkernel failed in module $_d_mod"
exit 1
}
else
- module_install "$_d_mod"
+ module_install "$_d_mod" "$moddir"
if [[ $no_kernel != yes ]]; then
- module_installkernel "$_d_mod" || {
+ module_installkernel "$_d_mod" "$moddir" || {
dfatal "installkernel failed in module $_d_mod"
exit 1
}
## final stuff that has to happen
if [[ $no_kernel != yes ]]; then
+ if [[ $hostonly_mode = "strict" ]]; then
+ cp "$DRACUT_KERNEL_MODALIASES" $initdir/lib/dracut/hostonly-kernel-modules.txt
+ fi
if [[ $drivers ]]; then
hostonly='' instmods $drivers
fi
- if [[ $add_drivers ]]; then
+ if [[ -n "${add_drivers// }" ]]; then
hostonly='' instmods -c $add_drivers
fi
if [[ $force_drivers ]]; then
cat "$f" >> "${initdir}/etc/fstab"
done
- if [[ $systemdutildir ]]; then
+ if [[ $dracutsysrootdir$systemdutildir ]]; then
if [ -d ${initdir}/$systemdutildir ]; then
mkdir -p ${initdir}/etc/conf.d
{
if [[ $DRACUT_RESOLVE_LAZY ]] && [[ $DRACUT_INSTALL ]]; then
dinfo "*** Resolving executable dependencies ***"
find "$initdir" -type f -perm /0111 -not -path '*.ko' -print0 \
- | xargs -r -0 $DRACUT_INSTALL ${initdir:+-D "$initdir"} -R ${DRACUT_FIPS_MODE:+-f} --
- dinfo "*** Resolving executable dependencies done***"
+ | xargs -r -0 $DRACUT_INSTALL ${initdir:+-D "$initdir"} ${dracutsysrootdir:+-r "$dracutsysrootdir"} -R ${DRACUT_FIPS_MODE:+-f} --
+ dinfo "*** Resolving executable dependencies done ***"
fi
+ # Now we are done with lazy resolving, always install dependencies
+ unset DRACUT_RESOLVE_LAZY
+ export DRACUT_RESOLVE_DEPS=1
+
# libpthread workaround: pthread_cancel wants to dlopen libgcc_s.so
for _dir in $libdirs; do
- for _f in "$_dir/libpthread.so"*; do
+ for _f in "$dracutsysrootdir$_dir/libpthread.so"*; do
[[ -e "$_f" ]] || continue
inst_libdir_file "libgcc_s.so*"
break 2
if [[ $src && $target ]]; then
if [[ -f $src ]]; then
inst $src $target
- else
+ elif [[ -d $src ]]; then
ddebug "Including directory: $src"
destdir="${initdir}/${target}"
mkdir -p "$destdir"
mkdir -m 0755 -p "$object_destdir"
chmod --reference="$objectname" "$object_destdir"
fi
- $DRACUT_CP -t "$object_destdir" "$objectname"/*
+ $DRACUT_CP -t "$object_destdir" "$dracutsysrootdir$objectname"/*
else
- $DRACUT_CP -t "$destdir" "$objectname"
+ $DRACUT_CP -t "$destdir" "$dracutsysrootdir$objectname"
fi
done
+ elif [[ -e $src ]]; then
+ derror "$src is neither a directory nor a regular file"
+ else
+ derror "$src doesn't exist"
fi
fi
done
if [[ $kernel_only != yes ]]; then
# 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"
+ for f in $dracutsysrootdir/etc/ld.so.conf $dracutsysrootdir/etc/ld.so.conf.d/*; do
+ [[ -f $f ]] && inst_simple "${f#$dracutsysrootdir}"
done
- if ! ldconfig -r "$initdir"; then
+ if ! $DRACUT_LDCONFIG -r "$initdir" -f /etc/ld.so.conf; then
if [[ $EUID = 0 ]]; then
derror "ldconfig exited ungracefully"
else
fi
fi
-PRELINK_BIN="$(command -v prelink)"
-if [[ $EUID = 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
- elif [[ $do_prelink == yes ]]; then
- 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 [[ $do_hardlink = yes ]] && command -v hardlink >/dev/null; then
dinfo "*** Hardlinking files ***"
hardlink "$initdir" 2>&1
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_cmd -g 2>/dev/null
-
- # strip kernel modules, but do not touch signed modules
- find "$initdir" -type f -path '*/lib/modules/*.ko' -print0 \
- | while read -r -d $'\0' f || [ -n "$f" ]; do
- SIG=$(tail -c 28 "$f" | tr -d '\000')
- [[ $SIG == '~Module signature appended~' ]] || { printf "%s\000" "$f"; }
- done | xargs -r -0 $strip_cmd -g
+# cleanup empty ldconfig_paths directories
+for d in $(ldconfig_paths); do
+ rmdir -p --ignore-fail-on-non-empty "$initdir/$d" >/dev/null 2>&1
+done
- dinfo "*** Stripping files done ***"
-fi
if [[ $early_microcode = yes ]]; then
dinfo "*** Generating early-microcode cpio image ***"
ucode_dir=(amd-ucode intel-ucode)
for _fwdir in $fw_dir; do
if [[ -d $_fwdir && -d $_fwdir/$_fw ]]; then
_src="*"
- dinfo "*** Constructing ${ucode_dest[$idx]} ****"
+ dinfo "*** Constructing ${ucode_dest[$idx]} ***"
if [[ $hostonly ]]; then
_src=$(get_ucode_file)
[[ $_src ]] || break
+ [[ -r $_fwdir/$_fw/$_src ]] || _src="${_src}.early"
[[ -r $_fwdir/$_fw/$_src ]] || break
fi
fi
fi
+if dracut_module_included "squash"; then
+ dinfo "*** Install squash loader ***"
+ if ! check_kernel_config CONFIG_SQUASHFS; then
+ dfatal "CONFIG_SQUASHFS have to be enabled for dracut squash module to work"
+ exit 1
+ fi
+ if ! check_kernel_config CONFIG_OVERLAY_FS; then
+ dfatal "CONFIG_OVERLAY_FS have to be enabled for dracut squash module to work"
+ exit 1
+ fi
+ if ! check_kernel_config CONFIG_DEVTMPFS; then
+ dfatal "CONFIG_DEVTMPFS have to be enabled for dracut squash module to work"
+ exit 1
+ fi
+
+ readonly squash_dir="$initdir/squash/root"
+ readonly squash_img=$initdir/squash/root.img
+
+ # Currently only move "usr" "etc" to squashdir
+ readonly squash_candidate=( "usr" "etc" )
+
+ mkdir -m 0755 -p $squash_dir
+ for folder in "${squash_candidate[@]}"; do
+ mv $initdir/$folder $squash_dir/$folder
+ done
+
+ # Move some files out side of the squash image, including:
+ # - Files required to boot and mount the squashfs image
+ # - Files need to be accessible without mounting the squash image
+ required_in_root() {
+ local file=$1
+ local _sqsh_file=$squash_dir/$file
+ local _init_file=$initdir/$file
+
+ if [[ -e $_init_file ]]; then
+ return
+ fi
+
+ if [[ ! -e $_sqsh_file ]] && [[ ! -L $_sqsh_file ]]; then
+ derror "$file is required to boot a squashed initramfs but it's not installed!"
+ return
+ fi
+
+ if [[ ! -d $(dirname $_init_file) ]]; then
+ required_in_root $(dirname $file)
+ fi
+
+ if [[ -L $_sqsh_file ]]; then
+ cp --preserve=all -P $_sqsh_file $_init_file
+ _sqsh_file=$(realpath $_sqsh_file 2>/dev/null)
+ if [[ -e $_sqsh_file ]] && [[ "$_sqsh_file" == "$squash_dir"* ]]; then
+ # Relative symlink
+ required_in_root ${_sqsh_file#$squash_dir/}
+ return
+ fi
+ if [[ -e $squash_dir$_sqsh_file ]]; then
+ # Absolute symlink
+ required_in_root ${_sqsh_file#/}
+ return
+ fi
+ required_in_root ${module_spec#$squash_dir/}
+ else
+ if [[ -d $_sqsh_file ]]; then
+ mkdir $_init_file
+ else
+ mv $_sqsh_file $_init_file
+ fi
+ fi
+ }
+
+ required_in_root etc/initrd-release
+
+ for module_spec in $squash_dir/usr/lib/modules/*/modules.*;
+ do
+ required_in_root ${module_spec#$squash_dir/}
+ done
+
+ for dracut_spec in $squash_dir/usr/lib/dracut/*;
+ do
+ required_in_root ${dracut_spec#$squash_dir/}
+ done
+
+ mv $initdir/init $initdir/init.stock
+ ln -s squash/init.sh $initdir/init
+
+ # Reinstall required files for the squash image setup script.
+ # We have moved them inside the squashed image, but they need to be
+ # accessible before mounting the image.
+ inst_multiple "echo" "sh" "mount" "modprobe" "mkdir"
+ hostonly="" instmods "loop" "squashfs" "overlay"
+
+ # Only keep systemctl outsite if we need switch root
+ if [[ ! -f "$initdir/lib/dracut/no-switch-root" ]]; then
+ inst "systemctl"
+ fi
+
+ for folder in "${squash_candidate[@]}"; do
+ # Remove duplicated files in squashfs image, save some more space
+ [[ ! -d $initdir/$folder/ ]] && continue
+ for file in $(find $initdir/$folder/ -not -type d);
+ do
+ if [[ -e $squash_dir${file#$initdir} ]]; then
+ mv $squash_dir${file#$initdir} $file
+ fi
+ done
+ 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_cmd -g -p 2>/dev/null
+
+ # strip kernel modules, but do not touch signed modules
+ find "$initdir" -type f -path '*/lib/modules/*.ko' -print0 \
+ | while read -r -d $'\0' f || [ -n "$f" ]; do
+ SIG=$(tail -c 28 "$f" | tr -d '\000')
+ [[ $SIG == '~Module signature appended~' ]] || { printf "%s\000" "$f"; }
+ done | xargs -r -0 $strip_cmd -g -p
+ dinfo "*** Stripping files done ***"
+fi
+
+if dracut_module_included "squash"; then
+ dinfo "*** Squashing the files inside the initramfs ***"
+ mksquashfs $squash_dir $squash_img -no-xattrs -no-exports -noappend -always-use-fragments -comp xz -Xdict-size 100% -no-progress 1> /dev/null
+
+ if [[ $? != 0 ]]; then
+ dfatal "dracut: Failed making squash image"
+ exit 1
+ fi
+
+ rm -rf $squash_dir
+ dinfo "*** Squashing the files inside the initramfs done ***"
+fi
+
dinfo "*** Creating image file '$outfile' ***"
if [[ $uefi = yes ]]; then
echo -ne "\x00" >> "$uefi_outdir/cmdline.txt"
dinfo "Using UEFI kernel cmdline:"
- dinfo $(< "$uefi_outdir/cmdline.txt")
+ dinfo $(tr -d '\000' < "$uefi_outdir/cmdline.txt")
- [[ -s /usr/lib/os-release ]] && uefi_osrelease="/usr/lib/os-release"
- [[ -s /etc/os-release ]] && uefi_osrelease="/etc/os-release"
+ [[ -s $dracutsysrootdir/usr/lib/os-release ]] && uefi_osrelease="$dracutsysrootdir/usr/lib/os-release"
+ [[ -s $dracutsysrootdir/etc/os-release ]] && uefi_osrelease="$dracutsysrootdir/etc/os-release"
if objcopy \
${uefi_osrelease:+--add-section .osrel=$uefi_osrelease --change-section-vma .osrel=0x20000} \
--add-section .cmdline="${uefi_outdir}/cmdline.txt" --change-section-vma .cmdline=0x30000 \
--add-section .linux="$kernel_image" --change-section-vma .linux=0x40000 \
--add-section .initrd="${DRACUT_TMPDIR}/initramfs.img" --change-section-vma .initrd=0x3000000 \
- "$uefi_stub" "${uefi_outdir}/linux.efi" \
- && cp --reflink=auto "${uefi_outdir}/linux.efi" "$outfile"; then
- dinfo "*** Creating UEFI image file '$outfile' done ***"
+ "$uefi_stub" "${uefi_outdir}/linux.efi"; then
+ if [[ -n "${uefi_secureboot_key}" && -n "${uefi_secureboot_cert}" ]]; then \
+ if sbsign \
+ --key "${uefi_secureboot_key}" \
+ --cert "${uefi_secureboot_cert}" \
+ --output "$outfile" "${uefi_outdir}/linux.efi"; then
+ dinfo "*** Creating signed UEFI image file '$outfile' done ***"
+ else
+ dfatal "*** Creating signed UEFI image file '$outfile' failed ***"
+ exit 1
+ fi
+ else
+ if cp --reflink=auto "${uefi_outdir}/linux.efi" "$outfile"; then
+ dinfo "*** Creating UEFI image file '$outfile' done ***"
+ fi
+ fi
else
rm -f -- "$outfile"
dfatal "*** Creating UEFI image file '$outfile' failed ***"
command -v restorecon &>/dev/null && restorecon -- "$outfile"
-if ! sync "$outfile" 2> /dev/null; then
- dinfo "dracut: sync operartion on newly created initramfs $outfile failed"
- exit 1
+# We sync/fsfreeze only if we're operating on a live booted system.
+# It's possible for e.g. `kernel` to be installed as an RPM BuildRequires or equivalent,
+# and there's no reason to sync, and *definitely* no reason to fsfreeze.
+# Another case where this happens is rpm-ostree, which performs its own sync/fsfreeze
+# globally. See e.g. https://github.com/ostreedev/ostree/commit/8642ef5ab3fec3ac8eb8f193054852f83a8bc4d0
+if test -d $dracutsysrootdir/run/systemd/system; then
+ if ! sync "$outfile" 2> /dev/null; then
+ dinfo "dracut: sync operation on newly created initramfs $outfile failed"
+ exit 1
+ fi
+
+ # use fsfreeze only if we're not writing to /
+ if [[ "$(stat -c %m -- "$outfile")" != "/" && "$(stat -f -c %T -- "$outfile")" != "msdos" ]]; then
+ if ! $(fsfreeze -f $(dirname "$outfile") 2>/dev/null && fsfreeze -u $(dirname "$outfile") 2>/dev/null); then
+ dinfo "dracut: warning: could not fsfreeze $(dirname "$outfile")"
+ fi
+ fi
fi
exit 0