From: Böszörményi Zoltán Date: Fri, 25 Oct 2019 09:42:10 +0000 (+0200) Subject: Add documentation and Yocto examples X-Git-Tag: 050~106 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4efcd19a4ee86007cfd5f75982a03330b364e242;p=thirdparty%2Fdracut.git Add documentation and Yocto examples Signed-off-by: Böszörményi Zoltán --- diff --git a/README.cross b/README.cross new file mode 100644 index 000000000..809ccd738 --- /dev/null +++ b/README.cross @@ -0,0 +1,70 @@ +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". diff --git a/dracut.8.asc b/dracut.8.asc index 2e974fb0b..f1737f7ff 100644 --- a/dracut.8.asc +++ b/dracut.8.asc @@ -284,6 +284,15 @@ Default: Default: _/var/tmp_ +**-r, --sysroot** __:: + 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** __:: ssh key file used with ssh-client module. **--logfile** __:: logfile to use; overrides any setting from @@ -517,6 +526,91 @@ ENVIRONMENT _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_:: diff --git a/examples/yocto/classes/dracut.bbclass b/examples/yocto/classes/dracut.bbclass new file mode 100644 index 000000000..5c49b3fcd --- /dev/null +++ b/examples/yocto/classes/dracut.bbclass @@ -0,0 +1,116 @@ +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}" diff --git a/examples/yocto/postinst-intercepts/execute_dracut b/examples/yocto/postinst-intercepts/execute_dracut new file mode 100755 index 000000000..f9c51affe --- /dev/null +++ b/examples/yocto/postinst-intercepts/execute_dracut @@ -0,0 +1,44 @@ +#!/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" diff --git a/examples/yocto/recipes/cross-compiler-ldd/cross-compile-ldd-fix-infinite-loop.patch b/examples/yocto/recipes/cross-compiler-ldd/cross-compile-ldd-fix-infinite-loop.patch new file mode 100644 index 000000000..4aae731d1 --- /dev/null +++ b/examples/yocto/recipes/cross-compiler-ldd/cross-compile-ldd-fix-infinite-loop.patch @@ -0,0 +1,19 @@ +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" diff --git a/examples/yocto/recipes/cross-compiler-ldd_git.bb b/examples/yocto/recipes/cross-compiler-ldd_git.bb new file mode 100644 index 000000000..f8b7906ea --- /dev/null +++ b/examples/yocto/recipes/cross-compiler-ldd_git.bb @@ -0,0 +1,33 @@ +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}"