]> git.ipfire.org Git - thirdparty/dracut.git/blobdiff - dracut.sh
network-manager: remove useless use of basename
[thirdparty/dracut.git] / dracut.sh
index a4406dd94f0bf68ffc9ecfdda9c6cd019132e967..b85d06001b531ba8e4ed09251d9c2d6720ba5cc6 100755 (executable)
--- a/dracut.sh
+++ b/dracut.sh
@@ -1,4 +1,4 @@
-#!/bin/bash --norc
+#!/bin/bash -p
 #
 # Generator script for a dracut initramfs
 # Tries to retain some degree of compatibility with the command line
@@ -23,6 +23,8 @@
 
 # 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
@@ -108,8 +110,6 @@ Creates initial ramdisk images for preloading modules
   --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]
@@ -147,6 +147,21 @@ Creates initial ramdisk images for preloading modules
   -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
@@ -334,8 +349,6 @@ rearrange_params()
         --long kernel-cmdline: \
         --long strip \
         --long nostrip \
-        --long prelink \
-        --long noprelink \
         --long hardlink \
         --long nohardlink \
         --long noprefix \
@@ -354,6 +367,7 @@ rearrange_params()
         --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 \
@@ -460,9 +474,6 @@ if [[ $append_args_l == "yes" ]]; then
         eval set -- "$TEMP"
         rearrange_params "$@"
     fi
-
-    # clean the temporarily used scratch-pad directory
-    rm -rf $scratch_dir
 fi
 
 unset PARMS_TO_STORE
@@ -520,8 +531,6 @@ while :; do
                        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="/";;
@@ -544,6 +553,8 @@ while :; do
                        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)
@@ -724,14 +735,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_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
@@ -762,6 +772,16 @@ if ! [[ $outfile ]]; then
     fi
 
     if [[ $uefi == "yes" ]]; then
+        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 /etc/os-release /usr/lib/os-release \
                        | while read -r line || [[ $line ]]; do \
                        [[ $line =~ BUILD_ID\=* ]] && eval "$line" && echo "$BUILD_ID" && break; \
@@ -856,6 +876,19 @@ 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")"
@@ -1288,16 +1321,16 @@ done
 [[ -d $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
+    [[ -e /lib/udev/ata_id ]] && udevdir=/lib/udev
+    [[ -e /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
+    [[ -e /lib/systemd/systemd-udevd ]] && systemdutildir=/lib/systemd
+    [[ -e /usr/lib/systemd/systemd-udevd ]] && systemdutildir=/usr/lib/systemd
 fi
 
 [[ -d $systemdsystemunitdir ]] \
@@ -1350,7 +1383,7 @@ do_print_cmdline()
     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
 }
@@ -1431,14 +1464,14 @@ for moddir in "$dracutbasedir/modules.d"/[0-9][0-9]*; do
         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
             }
@@ -1466,6 +1499,9 @@ dinfo "*** Including modules done ***"
 
 ## final stuff that has to happen
 if [[ $no_kernel != yes ]]; then
+    if [[ $hostonly ]]; then
+        cp "$DRACUT_KERNEL_MODALIASES" $initdir/lib/dracut/hostonly-kernel-modules.txt
+    fi
 
     if [[ $drivers ]]; then
         hostonly='' instmods $drivers
@@ -1546,7 +1582,7 @@ if [[ $kernel_only != yes ]]; 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***"
+        dinfo "*** Resolving executable dependencies done ***"
     fi
 
     # Now we are done with lazy resolving, always install dependencies
@@ -1608,21 +1644,6 @@ if [[ $kernel_only != yes ]]; then
     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
@@ -1652,14 +1673,14 @@ 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
+        | 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
+    done | xargs -r -0 $strip_cmd -g -p
 
     dinfo "*** Stripping files done ***"
 fi
@@ -1679,7 +1700,7 @@ if [[ $early_microcode = yes ]]; then
         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
@@ -1736,6 +1757,120 @@ fi
 
 dinfo "*** Creating image file '$outfile' ***"
 
+if dracut_module_included "squash"; then
+    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="${DRACUT_TMPDIR}/squashfs"
+    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
+
+    mksquashfs $squash_dir $squash_img -comp xz -b 64K -Xdict-size 100% &> /dev/null
+
+    if [[ $? != 0 ]]; then
+        dfatal "dracut: Failed making squash image"
+        exit 1
+    fi
+fi
+
 if [[ $uefi = yes ]]; then
     readonly uefi_outdir="$DRACUT_TMPDIR/uefi"
     mkdir "$uefi_outdir"
@@ -1817,9 +1952,22 @@ if [[ $uefi = yes ]]; then
            --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 ***"