From 2873ada888a1390179b768049c6f984cbc57cb19 Mon Sep 17 00:00:00 2001 From: Frederick Grose Date: Sun, 23 Jul 2023 17:00:29 -0400 Subject: [PATCH 1/5] feat(module-postprocess): provide a postprocessing loop for modules Provide code for postprocessing the build after all modules have been loaded by enrolling those modules with a postprocess() function in their module_setup.sh into the variable $mods_to_postprocess. Update the documentation in dracut.modules.7.asc and HACKING.md files. Also, include a missing dinfo message before including modules. This feature is demonstrated in three upcoming commits: feat(99~no~sh): allow a build without any command shell fix(00bash): fail if Bash below version 4.4 is linked to /bin/sh refactor(99squash): gather code into the squash module --- docs/HACKING.md | 12 ++++++++++++ dracut-init.sh | 16 ++++++++++++++++ dracut.sh | 18 +++++++++++++++++- man/dracut.modules.7.asc | 23 +++++++++++++++-------- 4 files changed, 60 insertions(+), 9 deletions(-) diff --git a/docs/HACKING.md b/docs/HACKING.md index 74dd7800bb..1f683e819a 100644 --- a/docs/HACKING.md +++ b/docs/HACKING.md @@ -174,6 +174,18 @@ dracut_install_dir/modules.d/ which rely on the network module to detect and configure network interfaces. +`postprocess()`: + This function of module-setup.sh is invoked by dracut in a + postprocessing loop (after all module files have been installed and all + other module scripts have run) if the variable _$mods_to_postprocess_ + is enrolled with module information structured in a space-separated list + like `" module:moddir[@action@...] ... "`. For example, the squash + module employs this feature with action 'installpost' like this, + `mods_to_postprocess+=" squash:$moddir@installpost@ "`, in order to move + files into a `../squash/root/` directory in preparation for squashing + the image. A second call to `postprocess()` is made after striping + object files when the image is ready for squashing. + Any other files in the module will not be touched by dracut directly. You are encouraged to provide a README that describes what the module is for. diff --git a/dracut-init.sh b/dracut-init.sh index ff1d4e3bd2..9a4a7729b6 100755 --- a/dracut-init.sh +++ b/dracut-init.sh @@ -916,6 +916,22 @@ module_installkernel() { fi } +# [action=] module_postprocess +# Execute the postprocess() function of module-setup.sh of with +# optional action directive. +module_postprocess() { + local _moddir=$2 + local _ret + unset -f 'postprocess' + postprocess() { true; } + # shellcheck disable=SC1090 + . "$_moddir"/module-setup.sh + moddir=$_moddir postprocess + _ret=$? + unset -f 'postprocess' + return $_ret +} + # check_mount [] [] # check_mount checks, if a dracut module is needed for the given # device and filesystem types in "${host_fs_types[@]}" diff --git a/dracut.sh b/dracut.sh index f17e789ab3..bf571a3f67 100755 --- a/dracut.sh +++ b/dracut.sh @@ -1783,7 +1783,7 @@ done export initdir dracutbasedir \ dracutmodules force_add_dracutmodules add_dracutmodules omit_dracutmodules \ - mods_to_load \ + mods_to_load mods_to_postprocess \ fw_dir drivers_dir debug no_kernel kernel_only \ omit_drivers mdadmconf lvmconf root_devs \ use_fstab fstab_lines libdirs fscks nofscks ro_mnt \ @@ -1794,6 +1794,7 @@ export initdir dracutbasedir \ hostonly_cmdline loginstall mods_to_load="" +mods_to_postprocess="" # 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 @@ -1896,6 +1897,7 @@ fi _isize=0 #initramfs size modules_loaded=" " # source our modules. +dinfo "*** Including modules ***" for moddir in "$dracutbasedir/modules.d"/[0-9][0-9]*; do _d_mod=${moddir##*/} _d_mod=${_d_mod#[0-9][0-9]} @@ -2230,6 +2232,15 @@ if [[ $kernel_only != yes ]]; then build_ld_cache fi +for _d_mod in $mods_to_postprocess; do + # $_d_mod here includes structured info as module:moddir[@action@...] + strstr "$_d_mod" "@installpost@" && { + _d_mod=${_d_mod/@installpost/} + _moddir=${_d_mod%@*} + action=installpost module_postprocess "${_d_mod%:*}" "${_moddir#*:}" + } +done + if dracut_module_included "squash"; then readonly squash_dir="$initdir/squash/root" readonly squash_img="$initdir/squash-root.img" @@ -2255,6 +2266,11 @@ if [[ $do_strip == yes ]] && ! [[ $DRACUT_FIPS_MODE ]]; then dinfo "*** Stripping files done ***" fi +for _d_mod in $mods_to_postprocess; do + _d_mod=${_d_mod%%@*} + module_postprocess "${_d_mod%:*}" "${_d_mod#*:}" +done + if dracut_module_included "squash"; then dinfo "*** Squashing the files inside the initramfs ***" declare squash_compress_arg diff --git a/man/dracut.modules.7.asc b/man/dracut.modules.7.asc index 3c056430f0..01383d96cc 100644 --- a/man/dracut.modules.7.asc +++ b/man/dracut.modules.7.asc @@ -22,16 +22,23 @@ point of time in which they are executed, are described in <>. The main script, which creates the initramfs is dracut itself. It parses all arguments and sets up the directory, in which everything is installed. It then -executes all check, install, installkernel scripts found in the modules, which -are to be processed. After everything is installed, the install directory is -archived and compressed to the final initramfs image. All helper functions used -by check, install and installkernel are found in in the file _dracut-functions_. -These shell functions are available to all module installer (install, -installkernel) scripts, without the need to source _dracut-functions_. +executes all check, install, installkernel, or module_setup scripts found in +the modules, which are to be processed. After everything is installed and +before the install directory is archived and compressed to the final initramfs +image, a postprocessing loop will run any postprocess() functions in a module's +module_setup.sh that has been enrolled in the variable $mods_to_postprocess. +This enables adjustments to be made to the installed image once all other +module scripts have completed. All helper functions used by check, install, +installkernel, and module_setup are found in in the file _dracut-functions_. +These shell functions are available to all module installer (check, install, +installkernel, module_setup) scripts, without the need to source +_dracut-functions_. A module can check the preconditions for install and installkernel with the -check script. Also dependencies can be expressed with check. If a module passed -check, install and installkernel will be called to install all of the necessary +check or module_setup script. Also dependencies can be expressed with check or +within module_setup with the depends() function. If a module passed check or +module_setup:check(), then install and installkernel or module_setup:install() +and module_setup:installkernel() will be called to install all of the necessary files for the module. To split between kernel and non-kernel parts of the installation, all kernel module related parts have to be in installkernel. All other files found in a module directory are module specific and mostly are hook From ef9faa253455bb40b2a8249737cb2834ef710b1e Mon Sep 17 00:00:00 2001 From: Frederick Grose Date: Sun, 23 Jul 2023 18:00:12 -0400 Subject: [PATCH 2/5] feat(99~sh): assure explicit installation of a command shell Introduce a new meta module '99~sh' and assure that its depends() function runs at the end of the 'for_each_module_dir()' loop by using LC_COLLATE=C in that function so that the '99~sh' meta module sorts after other normally named modules. Background: Implicit installation of command shells may occur during the *** Resolving executable dependencies *** phase of dracut.sh with the default flag $DRACUT_RESOLVE_LAZY=1. Any module script file with a shebang interpreter directive will trigger the installation of that command interpreter, typically /bin/sh, unless that interpreter has already been installed. Such implicit installations bypass any conditions encoded in their dracut module dependency checks and should be precluded. If the dracut -m, --modules option is used (outside of -m 'auto'), no module-setup.sh level code is invoked during the 'for_each_module_dir check_module' loop for any modules other than those specified in the -m option arguments. For this reason, in this case invoke module_depends ~sh. To allow an initramfs to be built without any command shell, as currently allowed (such as when the -m option is used or when incrementally building the initramfs with --rebuild), a new meta module '99~no~sh' will be introduced in a following commit. --- dracut-init.sh | 17 +++++---- dracut.sh | 2 ++ man/dracut.modules.7.asc | 13 +++++++ modules.d/99base/module-setup.sh | 5 --- modules.d/99~sh/module-setup.sh | 59 ++++++++++++++++++++++++++++++++ 5 files changed, 85 insertions(+), 11 deletions(-) create mode 100644 modules.d/99~sh/module-setup.sh diff --git a/dracut-init.sh b/dracut-init.sh index 9a4a7729b6..fdbeab07ac 100755 --- a/dracut-init.sh +++ b/dracut-init.sh @@ -949,11 +949,13 @@ check_mount() { [[ " $mods_to_load " == *\ $_mod\ * ]] && return 0 [[ " $mods_checked_as_dep " == *\ $_mod\ * ]] && return 1 - # This should never happen, but... - [[ -d $_moddir ]] || return 1 - [[ $2 ]] || mods_checked_as_dep+=" $_mod " + [[ -d $_moddir ]] || { + dwarn "Module '$_mod' cannot be installed without a source directory, '$_moddir'." + return 1 + } + # shellcheck disable=SC2154 if [[ " $omit_dracutmodules " == *\ $_mod\ * ]]; then return 1 @@ -1015,11 +1017,13 @@ check_module() { [[ " $mods_to_load " == *\ $_mod\ * ]] && return 0 [[ " $mods_checked_as_dep " == *\ $_mod\ * ]] && return 1 - # This should never happen, but... - [[ -d $_moddir ]] || return 1 - [[ $2 ]] || mods_checked_as_dep+=" $_mod " + [[ -d $_moddir ]] || { + dwarn "Module '$_mod' cannot be installed without a source directory, '$_moddir'." + return 1 + } + if [[ " $omit_dracutmodules " == *\ $_mod\ * ]]; then ddebug "Module '$_mod' will not be installed, because it's in the list to be omitted!" return 1 @@ -1083,6 +1087,7 @@ for_each_module_dir() { local _moddir local _func local _reason + LC_COLLATE=C _func=$1 for _moddir in "$dracutbasedir/modules.d"/[0-9][0-9]*; do [[ -d $_moddir ]] || continue diff --git a/dracut.sh b/dracut.sh index bf571a3f67..e96d62af16 100755 --- a/dracut.sh +++ b/dracut.sh @@ -1799,6 +1799,8 @@ mods_to_postprocess="" # This builds a list of modules that we will install next. for_each_module_dir check_module for_each_module_dir check_mount +# Assure an explicit command shell or ~no~sh. +[[ $dracutmodules == all ]] || module_depends ~sh "$(dracut_module_path ~sh)" dracut_module_included "fips" && export DRACUT_FIPS_MODE=1 diff --git a/man/dracut.modules.7.asc b/man/dracut.modules.7.asc index 01383d96cc..1292db5738 100644 --- a/man/dracut.modules.7.asc +++ b/man/dracut.modules.7.asc @@ -44,6 +44,19 @@ installation, all kernel module related parts have to be in installkernel. All other files found in a module directory are module specific and mostly are hook scripts and udev rules. +=== Command Shells === +A dracut build runs in Bash. Command scripts installed in the initramfs should +be POSIX compliant. DASH, Bash, mksh, and BusyBox are supported as command +shells and have dracut modules, _00dash_, _00bash_, _00mksh_, and _05busybox_. +The meta module _99~sh_ is provided to assure that a command shell is properly +installed during a build. An alternative command shell may be specified by +adding a module for it into the `../dracut/modules.d/` directory and linking +its executable to `/bin/sh` of the host. After dracut installs all specified +and dependent modules, it will loop through all installed executables and +install any dynamic dependencies found by _ldd_ and any command interpreters +found in shebang directives. The meta module _99~no~sh_ may be used to +opt out of automatic shell installation should that be desired during an +incremental or `-m`, `--modules` exclusive build. [[stages]] == Boot Process Stages diff --git a/modules.d/99base/module-setup.sh b/modules.d/99base/module-setup.sh index 54b0deb914..362d66d170 100755 --- a/modules.d/99base/module-setup.sh +++ b/modules.d/99base/module-setup.sh @@ -24,11 +24,6 @@ install() { ln -s dracut-util "${initdir}/usr/bin/dracut-getarg" ln -s dracut-util "${initdir}/usr/bin/dracut-getargs" - if [ ! -e "${initdir}/bin/sh" ]; then - inst_multiple bash - (ln -s bash "${initdir}/bin/sh" || :) - fi - # add common users in /etc/passwd, it will be used by nfs/ssh currently # use password for hostonly images to facilitate secure sulogin in emergency console [[ $hostonly ]] && pwshadow='x' diff --git a/modules.d/99~sh/module-setup.sh b/modules.d/99~sh/module-setup.sh new file mode 100644 index 0000000000..4dcd754905 --- /dev/null +++ b/modules.d/99~sh/module-setup.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# This file is part of dracut. +# SPDX-License-Identifier: GPL-2.0-or-later + +# This meta module is called from dracut. + +check() { + + depends + # We only want to return 255 since this is a meta module. + return 255 + +} + +depends() { + + local _sh _shells _shells_pattern + + # Assure an explicitly installed command shell. + + # An alternative command shell may be specified by adding a module to + # ../dracut/modules.d/ and linking its executable to /bin/sh of the host. + _sh=$(realpath -e /bin/sh) + _sh=${_sh##*/} + _shells='dash bash mksh busybox ~no~sh' + strstr " $_shells " " $_sh " || _shells="${_sh:+$_sh }$_shells" + + for _sh in $_shells; do + _shells_pattern+="* $_sh *|" + done + + strstr " $mods_to_load " " ~no~sh " && { + # If a shell is queued (explicitly or by a module level dependency, + # but not an executable dependency), then ignore ~no~sh. + # ~no~sh masks executable dependencies for /bin/sh. + [[ ${mods_to_load/ ~no~sh/} == @(${_shells_pattern%|}) ]] && { + mods_to_load=${mods_to_load/ ~no~sh/} + mods_to_postprocess=${mods_to_postprocess/ ~no~sh:* /} + } + } + + [[ " $mods_to_load " == @(${_shells_pattern%|}) ]] || { + for _sh in $_shells; do + add_dracutmodules+=" $_sh " + check_module "$_sh" + [[ $? == @(0|255) ]] || { + add_dracutmodules=${add_dracutmodules/" $_sh "/} + continue + } + [[ $dracutmodules == all ]] && echo "$_sh" + # We only want to return 255 since this is a meta module. + return 255 + done + dfatal "One of the command shells, '$_shells', must be made available." + exit 1 + } + # We only want to return 255 since this is a meta module. + return 255 +} From 48c7205fe073c86bb580ae8299ad5c778f73b4a9 Mon Sep 17 00:00:00 2001 From: Frederick Grose Date: Sun, 23 Jul 2023 18:47:13 -0400 Subject: [PATCH 3/5] feat(99~no~sh): allow a build without any command shell Install a null link to /bin/sh in order to satisfy the executable dependency checks and remove it in a postprocess() function. A no-command-shell-build may be desired when the -m, --modules option is used or when incrementally building an initramfs with --rebuild. This module provides an opt-out to the automatic specification of a command shell introduced with 99~sh. --- modules.d/99~no~sh/module-setup.sh | 32 ++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 modules.d/99~no~sh/module-setup.sh diff --git a/modules.d/99~no~sh/module-setup.sh b/modules.d/99~no~sh/module-setup.sh new file mode 100644 index 0000000000..766eee2b2b --- /dev/null +++ b/modules.d/99~no~sh/module-setup.sh @@ -0,0 +1,32 @@ +#!/bin/bash +# This file is part of dracut. +# SPDX-License-Identifier: GPL-2.0-or-later + +# This meta module is included when no command shell is desired. + +check() { + + # We only want to return 255 since this is a meta module. + return 255 + +} + +install() { + + # Enroll module for postprocessing. + mods_to_postprocess+=" ~no~sh:$moddir@installpost@ " + + # Installing a null link satisfies the executable dependency check. + ln -sf ../../dev/null "${initdir}"/bin/sh + +} + +postprocess() { + + [[ $action == installpost ]] && { + # Remove the faked installation link. + rm "${initdir}"/usr/bin/sh + return $? + } + return 0 +} From 7e265ec37fce1038ff34c6bab37ccf00d1dc123f Mon Sep 17 00:00:00 2001 From: Frederick Grose Date: Mon, 24 Jul 2023 01:14:29 -0400 Subject: [PATCH 4/5] fix(00bash): fail if Bash below version 4.4 is linked to /bin/sh At least bash-4.4 (from 2016-09-15) is required for proper xtrace logging when Bash is the initramfs command shell. This requirement was introduced in commit 10cf8e4 on 2022-12-30 with the feature, local -, which automates the restoration of local xtrace & other set options. --- modules.d/00bash/module-setup.sh | 27 +++++++++++++++++++++++++++ modules.d/99~sh/module-setup.sh | 3 +++ 2 files changed, 30 insertions(+) diff --git a/modules.d/00bash/module-setup.sh b/modules.d/00bash/module-setup.sh index 89ef65414b..bf7cf399fc 100755 --- a/modules.d/00bash/module-setup.sh +++ b/modules.d/00bash/module-setup.sh @@ -5,6 +5,11 @@ # Prerequisite check(s) for module. check() { + # Enroll module for postprocessing. + strstr " $mods_to_postprocess " " bash:$moddir@installpost@ " || { + mods_to_postprocess+=" bash:$moddir@installpost@ " + } + # If the binary(s) requirements are not fulfilled the module can't be installed. require_binaries bash || return 1 @@ -30,3 +35,25 @@ install() { [[ -L $initdir/bin/sh ]] || ln -sf bash "${initdir}/bin/sh" } + +# Execute any postprocessing requirements. +postprocess() { + + [[ $action == installpost ]] && { + [[ $(readlink "${initdir}"/bin/sh) == bash ]] && { + local version ver0 ver1 + + # local - (available since bash-4.4 2016-09-15) automates the + # restoration of local xtrace & other set options. + IFS=' ' read -r -a version <<< "$(command /bin/bash --version)" + IFS=. read -r ver0 ver1 _ <<< "${version[3]}" + if ((${ver0}${ver1} < 44)); then + dfatal "Installed Bash ${version[3]} ${version[4]}. + At least Bash 4.4 is required for proper xtrace logging + when Bash is the initramfs command shell." + exit 1 + fi + } + } + return 0 +} diff --git a/modules.d/99~sh/module-setup.sh b/modules.d/99~sh/module-setup.sh index 4dcd754905..3a4b3e0933 100644 --- a/modules.d/99~sh/module-setup.sh +++ b/modules.d/99~sh/module-setup.sh @@ -39,6 +39,9 @@ depends() { } } + # Always module_check bash to enroll it for postprocessing. + module_check bash + [[ " $mods_to_load " == @(${_shells_pattern%|}) ]] || { for _sh in $_shells; do add_dracutmodules+=" $_sh " From 55e50c1f78e0d000d23cdfa679fdc834cfc91027 Mon Sep 17 00:00:00 2001 From: Frederick Grose Date: Mon, 24 Jul 2023 00:03:25 -0400 Subject: [PATCH 5/5] refactor(99squash): gather code into the squash module Move squash-module-specific code from dracut.sh to /99squash/module-setup.sh. Use dracut's new module_postprocess() feature. Make shell installation explicit, preferring busybox, if available. Clarify a comment about the dracut directory files. Also, make new shellcheck adjustments. --- dracut.sh | 37 +----------------- modules.d/99squash/module-setup.sh | 61 ++++++++++++++++++++++++++---- 2 files changed, 54 insertions(+), 44 deletions(-) diff --git a/dracut.sh b/dracut.sh index e96d62af16..3bcbf93895 100755 --- a/dracut.sh +++ b/dracut.sh @@ -2243,14 +2243,6 @@ for _d_mod in $mods_to_postprocess; do } done -if dracut_module_included "squash"; then - readonly squash_dir="$initdir/squash/root" - readonly squash_img="$initdir/squash-root.img" - mkdir -p "$squash_dir" - dinfo "*** Install squash loader ***" - DRACUT_SQUASH_POST_INST=1 module_install "squash" -fi - if [[ $do_strip == yes ]] && ! [[ $DRACUT_FIPS_MODE ]]; then # stripping files negates (dedup) benefits of using reflink [[ -n $enhanced_cpio ]] && ddebug "strip is enabled alongside cpio reflink" @@ -2270,36 +2262,9 @@ fi for _d_mod in $mods_to_postprocess; do _d_mod=${_d_mod%%@*} - module_postprocess "${_d_mod%:*}" "${_d_mod#*:}" + squash_compress=$squash_compress module_postprocess "${_d_mod%:*}" "${_d_mod#*:}" done -if dracut_module_included "squash"; then - dinfo "*** Squashing the files inside the initramfs ***" - declare squash_compress_arg - # shellcheck disable=SC2086 - if [[ $squash_compress ]]; then - if ! mksquashfs /dev/null "$DRACUT_TMPDIR"/.squash-test.img -no-progress -comp $squash_compress &> /dev/null; then - dwarn "mksquashfs doesn't support compressor '$squash_compress', failing back to default compressor." - else - squash_compress_arg="$squash_compress" - fi - fi - - # shellcheck disable=SC2086 - if ! mksquashfs "$squash_dir" "$squash_img" \ - -no-xattrs -no-exports -noappend -no-recovery -always-use-fragments \ - -no-progress ${squash_compress_arg:+-comp $squash_compress_arg} 1> /dev/null; then - dfatal "Failed making squash image" - exit 1 - fi - - rm -rf "$squash_dir" - dinfo "*** Squashing the files inside the initramfs done ***" - - # Skip initramfs compress - compress="cat" -fi - dinfo "*** Creating image file '$outfile' ***" if [[ $uefi == yes ]]; then diff --git a/modules.d/99squash/module-setup.sh b/modules.d/99squash/module-setup.sh index dc2e0a2059..dfe6aab121 100755 --- a/modules.d/99squash/module-setup.sh +++ b/modules.d/99squash/module-setup.sh @@ -8,13 +8,29 @@ check() { } depends() { + + if find_binary busybox &> /dev/null \ + && ! strstr " $omit_dracutmodules " " busybox "; then + echo "busybox" + fi echo "systemd-initrd" return 0 } +install() { + + # Enroll module for postprocessing. + # shellcheck disable=SC2154 + mods_to_postprocess+=" squash:$moddir@installpost@ " + +} + installpost() { - local _busybox - _busybox=$(find_binary busybox) + # shellcheck disable=SC2154 + readonly squash_dir="$initdir/squash/root" + readonly squash_img="$initdir/squash-root.img" + mkdir -p "$squash_dir" + dinfo "*** Install squash loader ***" # Move everything under $initdir except $squash_dir # itself into squash image @@ -26,16 +42,16 @@ installpost() { mkdir -p "$initdir"/squash/ mkdir -p "$squash_dir"/squash/ - # Copy dracut spec files out side of the squash image - # so dracut rebuild and lsinitrd can work + # Copy /dracut/ directory files out of the squash image directory + # so dracut rebuild and lsinitrd can work. for file in "$squash_dir"/usr/lib/dracut/*; do [[ -f $file ]] || continue DRACUT_RESOLVE_DEPS=1 dracutsysrootdir="$squash_dir" inst "${file#"$squash_dir"}" done # Install required modules and binaries for the squash image init script. - if [[ $_busybox ]]; then - inst "$_busybox" /usr/bin/busybox + if find_binary busybox; then + inst busybox /usr/bin/busybox for _i in sh echo mount modprobe mkdir switch_root grep umount; do ln_r /usr/bin/busybox /usr/bin/$_i done @@ -61,8 +77,37 @@ installpost() { build_ld_cache } -install() { - if [[ $DRACUT_SQUASH_POST_INST ]]; then +postprocess() { + + # shellcheck disable=SC2154 + [[ $action == installpost ]] && { installpost + return 0 + } + + dinfo "*** Squashing the files inside the initramfs ***" + declare squash_compress_arg + if [[ $squash_compress ]]; then + # shellcheck disable=SC2086 + if ! mksquashfs /dev/null "$DRACUT_TMPDIR"/.squash-test.img -no-progress -comp $squash_compress &> /dev/null; then + dwarn "mksquashfs doesn't support compressor '$squash_compress', falling back to default compressor." + else + squash_compress_arg="$squash_compress" + fi + fi + + # shellcheck disable=SC2086 + if ! mksquashfs "$squash_dir" "$squash_img" \ + -no-xattrs -no-exports -noappend -no-recovery -always-use-fragments \ + -no-progress ${squash_compress_arg:+-comp $squash_compress_arg} 1> /dev/null; then + dfatal "Failed making squash image" + exit 1 fi + + rm -rf "$squash_dir" + dinfo "*** Squashing the files inside the initramfs done ***" + + # Skip initramfs compress + export compress="cat" + }