--- /dev/null
+Dracut supports running against a sysroot directory that is different
+from the actual root (/) directory of the running system. It is most
+useful for creating/bootstrapping a new system that may or may not be
+using the same CPU architecture as the host system, i.e. building a
+whole Linux system with a cross-compiler framework like Yocto.
+
+The user-visible frontend change is the introduction of a new option
+called "-r" or "--sysroot". It expects a directory that contains the
+complete Linux system that has all the files (kernel drivers, firmware,
+executables, libraries and others) necessary to construct the initramfs.
+
+E.g: dracut --sysroot /path/to/sysroot initramfs.img kernelversion
+
+To support this, a new global variable was introduced inside dracut.
+This variable is called "dracutsysrootdir" and all the files installed
+into the initramfs image is searched relative to the sysroot directory.
+This variable can also be set externally to dracut without using option
+-r/--sysroot.
+
+There are other details that are necessary to tweak to be able to
+run on cross-compiled (a.k.a. foreign) binaries.
+
+dracut uses these crucial utilities during its operation:
+
+ldd
+===
+It lists dynamic library dependencies for executables or libraries
+
+ldconfig
+========
+It creates /etc/ld.so.cache, i.e. the cached information about libraries
+known to the system.
+
+These utilities the way they exist on the host system only work on
+the host system.
+
+To support cross-compiled binaries, a different ldd variant is needed that
+works on those binaries. One such ldd script is found at
+https://gist.github.com/jerome-pouiller/c403786c1394f53f44a3b61214489e6f
+
+ldconfig in GLIBC as is does support a sysroot with its -r option.
+
+Extra environment variables needed to run dracut on the sysroot are
+documented in the dracut(8) man page.
+
+For the Plymouth boot splash to be added to the initramfs image,
+this gitlab PR is needed for Plymouth:
+https://gitlab.freedesktop.org/plymouth/plymouth/merge_requests/72
+
+Extensions to be used with Yocto
+================================
+
+examples/yocto/classes/dracut.bbclass:
+ Bitbake class for running dracut during the "do_rootfs" stage of
+ creating a distribution image and from the postinstall script of
+ a package. A kernel recipe needs this line to activate it:
+
+ inherit dracut
+
+examples/yocto/postinst-intercepts/execute_dracut
+ The "intercept" script used during "do_rootfs" mentioned above.
+
+examples/yocto/recipes/cross-compiler-ldd_git.bb
+ Package recipe for the cross-compiler-ldd script from the above link.
+
+All the above three need to be added to a Yocto layer to their
+proper locations.
+
+They were tested on Yocto 2.7 with MACHINE="intel-core2-32" and
+MACHINE="genericx86-64".
Default:
_/var/tmp_
+**-r, --sysroot** _<sysroot directory>_::
+ specify the sysroot directory to collect files from.
+ This is useful to create the initramfs image from
+ a cross-compiled sysroot directory. For the extra helper
+ variables, see *ENVIRONMENT* below.
++
+Default:
+ _empty_
+
**--sshkey** _<sshkey file>_:: ssh key file used with ssh-client module.
**--logfile** _<logfile>_:: logfile to use; overrides any setting from
_INITRD_COMPRESS_::
sets the default compression program. See **--compress**.
+_DRACUT_LDCONFIG_::
+ sets the _ldconfig_ program path and options. Optional.
+ Used for **--sysroot**.
++
+Default:
+ _ldconfig_
+
+_DRACUT_LDD_::
+ sets the _ldd_ program path and options. Optional.
+ Used for **--sysroot**.
++
+Default:
+ _ldd_
+
+_DRACUT_TESTBIN_::
+ sets the initially tested binary for detecting library paths.
+ Optional. Used for **--sysroot**. In the cross-compiled sysroot,
+ the default value (_/bin/sh_) is unusable, as it is an absolute
+ symlink and points outside the sysroot directory.
++
+Default:
+ _/bin/sh_
+
+_DRACUT_INSTALL_::
+ overrides path and options for executing _dracut-install_ internally.
+ Optional. Can be used to debug _dracut-install_ while running the
+ main dracut script.
++
+Default:
+ _dracut-install_
++
+Example:
+ DRACUT_INSTALL="valgrind dracut-install"
+
+_DRACUT_COMPRESS_BZIP2_::
+_DRACUT_COMPRESS_BZIP2_::
+_DRACUT_COMPRESS_LBZIP2_::
+_DRACUT_COMPRESS_LZMA_::
+_DRACUT_COMPRESS_XZ_::
+_DRACUT_COMPRESS_GZIP_::
+_DRACUT_COMPRESS_PIGZ_::
+_DRACUT_COMPRESS_LZOP_::
+_DRACUT_COMPRESS_ZSTD_::
+_DRACUT_COMPRESS_LZ4_::
+_DRACUT_COMPRESS_CAT_::
+ overrides for compression utilities to support using them from
+ non-standard paths.
++
+Default values are the default compression utility names to be found in **PATH**.
+
+_DRACUT_ARCH_::
+ overrides the value of **uname -m**. Used for **--sysroot**.
++
+Default:
+ _empty_ (the value of **uname -m** on the host system)
+
+_SYSTEMD_VERSION_::
+ overrides systemd version. Used for **--sysroot**.
+
+_DRACUT_INSTALL_PATH_::
+ overrides **PATH** environment for **dracut-install** to look for
+ binaries relative to **--sysroot**. In a cross-compiled environment
+ (e.g. Yocto), PATH points to natively built binaries that are not
+ in the host's /bin, /usr/bin, etc. **dracut-install** still needs plain
+ /bin and /usr/bin that are relative to the cross-compiled sysroot.
++
+Default:
+ _PATH_
+
+_DRACUT_INSTALL_LOG_TARGET_::
+ overrides **DRACUT_LOG_TARGET** for **dracut-install**. It allows
+ running **dracut-install* to run with different log target that
+ **dracut** runs with.
++
+Default:
+ _DRACUT_LOG_TARGET_
+
+_DRACUT_INSTALL_LOG_LEVEL_::
+ overrides **DRACUT_LOG_LEVEL** for **dracut-install**. It allows
+ running **dracut-install* to run with different log level that
+ **dracut** runs with.
++
+Default:
+ _DRACUT_LOG_LEVEL_
+
FILES
-----
_/var/log/dracut.log_::
--- /dev/null
+DRACUT_PN ??= "${PN}"
+
+def dracut_compression_type(d):
+ rdtype = d.getVar("INITRAMFS_FSTYPES", True).split('.')
+ if len(rdtype) != 2:
+ return ['','','']
+ if rdtype[0] != 'cpio':
+ return ['','','']
+ cmptypes = [['gz','--gzip','gzip'],['bz2', '--bzip2','bzip2'],['lzma','--lzma','xz'],['xz','--xz','xz'],['lzo','--lzo','lzo'],['lz4','--lz4','lz4'],['zstd','--zstd','zstd']]
+ for cmp in cmptypes:
+ if rdtype[1] == cmp[0]:
+ return cmp
+ return ['','','']
+
+def dracut_compression_opt(d):
+ cmp = dracut_compression_type(d)
+ return cmp[1]
+
+def dracut_compression_pkg(d):
+ cmp = dracut_compression_type(d)
+ return cmp[2]
+
+def dracut_compression_pkg_native(d):
+ cmp = dracut_compression_type(d)
+ if cmp[2] == '':
+ return ''
+ return cmp[2] + '-native'
+
+DRACUT_COMPRESS_OPT ??= "${@dracut_compression_opt(d)}"
+DRACUT_COMPRESS_PKG ??= "${@dracut_compression_pkg(d)}"
+DRACUT_COMPRESS_PKG_NATIVE ??= "${@dracut_compression_pkg_native(d)}"
+
+DRACUT_OPTS ??= "--early-microcode ${DRACUT_COMPRESS_OPT}"
+
+python __anonymous () {
+ pkg = d.getVar("DRACUT_PN", True)
+ if pkg != 'dracut':
+ d.appendVar("RDEPENDS_%s" % pkg, " dracut %s " % d.getVar("DRACUT_COMPRESS_PKG", True))
+ if not pkg.startswith('kernel'):
+ d.appendVarFlag("do_configure", "depends", "virtual/kernel:do_shared_workdir")
+ d.appendVarFlag("do_compile", "depends", "virtual/kernel:do_compile_kernelmodules")
+}
+
+export BUILD_TIME_KERNEL_VERSION = "${@oe.utils.read_file('${STAGING_KERNEL_BUILDDIR}/kernel-abiversion')}"
+
+dracut_postinst () {
+ MY_KERNEL_VERSION=$(readlink $D/boot/bzimage | sed 's,^.*bzImage-,,')
+ if [[ -z "$MY_KERNEL_VERSION" ]]; then
+ MY_KERNEL_VERSION="${KERNEL_VERSION}"
+ fi
+ if [[ -z "$MY_KERNEL_VERSION" ]]; then
+ MY_KERNEL_VERSION="${BUILD_TIME_KERNEL_VERSION}"
+ fi
+ if [[ -z "$MY_KERNEL_VERSION" ]]; then
+ exit 1
+ fi
+
+ if [ -n "$D" ]; then
+ #DEBUGOPTS="--debug --keep"
+ DEBUGOPTS="--keep"
+
+ $INTERCEPT_DIR/postinst_intercept execute_dracut ${PKG} mlprefix=${MLPREFIX} \
+ prefix= \
+ MY_KERNEL_VERSION=$MY_KERNEL_VERSION \
+ DEBUGOPTS="\"$DEBUGOPTS\"" \
+ DRACUT_OPTS="\"${DRACUT_OPTS}\"" \
+ systemdutildir=${systemd_unitdir} \
+ systemdsystemunitdir=${systemd_system_unitdir} \
+ systemdsystemconfdir=${sysconfdir}/systemd/system \
+ udevdir=${libdir}/udev \
+ DRACUT_TMPDIR=${WORKDIR}/dracut-tmpdir \
+ DRACUT_ARCH="${TUNE_ARCH}" \
+ DRACUT_COMPRESS_GZIP=$NATIVE_ROOT${bindir}/gzip \
+ DRACUT_COMPRESS_BZIP2=$NATIVE_ROOT${bindir}/bzip2 \
+ DRACUT_COMPRESS_LZMA=$NATIVE_ROOT${bindir}/lzma \
+ DRACUT_LDD="\"PATH='$PATH' ${STAGING_BINDIR_CROSS}/ldd --root $D\"" \
+ DRACUT_LDCONFIG=$NATIVE_ROOT${bindir}/ldconfig \
+ DRACUT_INSTALL="\"$NATIVE_ROOT${libdir}/dracut/dracut-install\"" \
+ PLYMOUTH_LDD="\"${STAGING_BINDIR_CROSS}/ldd --root $D\"" \
+ PLYMOUTH_LDD_PATH="'$PATH'" \
+ PLYMOUTH_PLUGIN_PATH=${libdir}/plymouth \
+ PLYMOUTH_THEME_NAME=${PLYMOUTH_THEME_NAME:-spinner} \
+ PLYMOUTH_THEME=${PLYMOUTH_THEME_NAME:-spinner}
+ else
+ depmod -a $MY_KERNEL_VERSION
+ echo RUNNING: dracut -f ${DRACUT_OPTS} /boot/initramfs.img $MY_KERNEL_VERSION
+ echo "dracut: $(dracut --help | grep 'Version:')"
+ dracut -f ${DRACUT_OPTS} /boot/initramfs.img $MY_KERNEL_VERSION
+ fi
+}
+
+dracut_populate_packages[vardeps] += "dracut_postinst"
+
+python dracut_populate_packages() {
+ localdata = d.createCopy()
+
+ pkg = d.getVar('DRACUT_PN', True)
+
+ postinst = d.getVar('pkg_postinst_%s' % pkg, True)
+ if not postinst:
+ postinst = '#!/bin/sh\n'
+ postinst += localdata.getVar('dracut_postinst', True)
+ d.setVar('pkg_postinst_%s' % pkg, postinst)
+}
+
+PACKAGESPLITFUNCS_prepend = "dracut_populate_packages "
+
+DRACUT_DEPENDS = " \
+ binutils-cross-${TUNE_ARCH} gcc-cross-${TUNE_ARCH} \
+ ldconfig-native coreutils-native findutils-native \
+ cpio-native util-linux-native kmod-native ${DRACUT_COMPRESS_PKG_NATIVE} \
+ dracut-native pkgconfig-native cross-compiler-ldd \
+ ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'systemd', '', d)} \
+ "
+DEPENDS_append_class-target = " ${DRACUT_DEPENDS}"
+PACKAGE_WRITE_DEPS_append = " ${DRACUT_DEPENDS}"
--- /dev/null
+#!/bin/sh
+
+set -e
+
+if [[ -z "$DRACUT_TMPDIR" ]]; then
+ echo "DRACUT_TMPDIR is unset, exiting"
+ exit 0
+fi
+
+# We have to unset "prefix" as dracut uses it to move files around.
+# Yocto has it set as part of the build environment.
+export prefix=
+
+# DRACUT settings
+export UDEVVERSION=241
+export SYSTEMD_VERSION=241
+export DRACUT_TESTBIN=/bin/bash.bash
+export DRACUT_INSTALL_PATH="/usr/sbin:/usr/bin:/sbin:/bin"
+
+# PLYMOUTH settings
+export PLYMOUTH_SYSROOT=$D
+
+export \
+ systemdutildir systemdsystemunitdir systemdsystemconfdir udevdir \
+ DRACUT_ARCH DRACUT_TESTBIN DRACUT_LDD DRACUT_LDCONFIG DRACUT_INSTALL \
+ DRACUT_COMPRESS_GZIP DRACUT_COMPRESS_BZIP2 DRACUT_COMPRESS_LZMA \
+ PLYMOUTH_LDD PLYMOUTH_LDD_PATH PLYMOUTH_PLUGIN_PATH \
+ PLYMOUTH_THEME_NAME PLYMOUTH_THEME
+
+# List environment for debugging
+echo ROOTFS-POSTINST-ENVIRONMENT
+echo -----------
+env
+echo -----------
+
+[[ -d $DRACUT_TMPDIR ]] || mkdir -p $DRACUT_TMPDIR
+
+# Execute depmod and dracut
+echo "$(date) - RUNNING: depmod -b $D -a $MY_KERNEL_VERSION"
+depmod -b $D -a $MY_KERNEL_VERSION
+echo "dracut: $(dracut --sysroot $D --help | grep 'Version:')"
+echo "$(date) - RUNNING: dracut -f --sysroot $D --tmpdir $DRACUT_TMPDIR $DRACUT_OPTS $DEBUGOPTS -k $D/lib/modules/$MY_KERNEL_VERSION $D/boot/initramfs.img $MY_KERNEL_VERSION"
+dracut -f --sysroot $D --tmpdir $DRACUT_TMPDIR $DRACUT_OPTS $DEBUGOPTS -k $D/lib/modules/$MY_KERNEL_VERSION $D/boot/initramfs.img $MY_KERNEL_VERSION
+echo "$(date) - DONE: dracut"
--- /dev/null
+diff --git a/cross-compile-ldd b/cross-compile-ldd
+index ef2ca20..332d57f 100644
+--- a/cross-compile-ldd
++++ b/cross-compile-ldd
+@@ -337,13 +337,13 @@ do_scan_etc_ldsoconf() {
+ # Build up the full list of search directories
+ declare -a needed_search_path
+ do_trace "Adding basic lib dirs\n"
+-ld_library_path="${ld_library_path}:"
+ while [ -n "${ld_library_path}" ]; do
+ d="${ld_library_path%%:*}"
+ if [ -n "${d}" ]; then
+ do_trace "-> adding search dir '%s'\n" "${d}"
+ needed_search_path+=( "${d}" )
+ fi
++ [[ "$ld_library_path" == "${ld_library_path#*:}" ]] && break
+ ld_library_path="${ld_library_path#*:}"
+ done
+ do_trace "Done adding basic lib dirs\n"
--- /dev/null
+SUMMARY = "Cross-compiler LDD"
+HOMEPAGE = "https://gist.github.com/c403786c1394f53f44a3b61214489e6f"
+BUGTRACKER = ""
+LICENSE = "GPLv2"
+
+LIC_FILES_CHKSUM = "file://cross-compile-ldd;beginline=53;endline=57;md5=2b29d19d18a430b931dda3750e865c84"
+
+SRCBRANCH = "master"
+SRCREV = "eb44581caf7dd60b149a6691abef46264c46e866"
+SRC_URI = " \
+ git://gist.github.com/c403786c1394f53f44a3b61214489e6f.git;protocol=https;branch=${SRCBRANCH} \
+ file://cross-compile-ldd-fix-infinite-loop.patch \
+ "
+
+S = "${WORKDIR}/git"
+
+inherit siteinfo
+
+SYSROOT_PREPROCESS_FUNCS += " cross_ldd_populate_sysroot "
+
+cross_ldd_populate_sysroot() {
+ mkdir -p ${SYSROOT_DESTDIR}${bindir_crossscripts}
+ cat ${S}/cross-compile-ldd | \
+ sed \
+ -e "s,^prefix=.*$,prefix=${TARGET_SYS}," \
+ -e "s,^bits=.*$,bits=${SITEINFO_BITS}," \
+ -e "s,^ld_library_path=.*$,ld_library_path=${LD_LIBRARY_PATH:-/lib:/usr/lib}," \
+ >${SYSROOT_DESTDIR}${bindir_crossscripts}/ldd
+ chmod +x ${SYSROOT_DESTDIR}${bindir_crossscripts}/ldd
+}
+
+DEPENDS = "coreutils-native sed-native binutils-cross-${TARGET_ARCH} gcc-cross-${TARGET_ARCH}"
+PACKAGE_WRITE_DEPS = "coreutils-native sed-native binutils-cross-${TARGET_ARCH} gcc-cross-${TARGET_ARCH}"