summaryrefslogtreecommitdiffstats
path: root/modules.d/98dracut-systemd
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-03 13:54:25 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-03 13:54:25 +0000
commit9cb1c4df7b9ce1a9ad1312621b0f2b16a94fba3a (patch)
tree2efb72864cc69e174c9c5ee33efb88a5f1553b48 /modules.d/98dracut-systemd
parentInitial commit. (diff)
downloaddracut-9cb1c4df7b9ce1a9ad1312621b0f2b16a94fba3a.tar.xz
dracut-9cb1c4df7b9ce1a9ad1312621b0f2b16a94fba3a.zip
Adding upstream version 060+5.upstream/060+5
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'modules.d/98dracut-systemd')
-rw-r--r--modules.d/98dracut-systemd/dracut-cmdline-ask.service32
-rwxr-xr-xmodules.d/98dracut-systemd/dracut-cmdline-ask.sh22
-rw-r--r--modules.d/98dracut-systemd/dracut-cmdline.service30
-rw-r--r--modules.d/98dracut-systemd/dracut-cmdline.service.8.asc26
-rwxr-xr-xmodules.d/98dracut-systemd/dracut-cmdline.sh75
-rw-r--r--modules.d/98dracut-systemd/dracut-emergency.service28
-rwxr-xr-xmodules.d/98dracut-systemd/dracut-emergency.sh59
-rw-r--r--modules.d/98dracut-systemd/dracut-initqueue.service28
-rw-r--r--modules.d/98dracut-systemd/dracut-initqueue.service.8.asc25
-rwxr-xr-xmodules.d/98dracut-systemd/dracut-initqueue.sh95
-rw-r--r--modules.d/98dracut-systemd/dracut-mount.service26
-rw-r--r--modules.d/98dracut-systemd/dracut-mount.service.8.asc25
-rwxr-xr-xmodules.d/98dracut-systemd/dracut-mount.sh38
-rw-r--r--modules.d/98dracut-systemd/dracut-pre-mount.service26
-rw-r--r--modules.d/98dracut-systemd/dracut-pre-mount.service.8.asc25
-rwxr-xr-xmodules.d/98dracut-systemd/dracut-pre-mount.sh19
-rw-r--r--modules.d/98dracut-systemd/dracut-pre-pivot.service35
-rw-r--r--modules.d/98dracut-systemd/dracut-pre-pivot.service.8.asc25
-rwxr-xr-xmodules.d/98dracut-systemd/dracut-pre-pivot.sh29
-rw-r--r--modules.d/98dracut-systemd/dracut-pre-trigger.service27
-rw-r--r--modules.d/98dracut-systemd/dracut-pre-trigger.service.8.asc25
-rwxr-xr-xmodules.d/98dracut-systemd/dracut-pre-trigger.sh21
-rw-r--r--modules.d/98dracut-systemd/dracut-pre-udev.service31
-rw-r--r--modules.d/98dracut-systemd/dracut-pre-udev.service.8.asc25
-rwxr-xr-xmodules.d/98dracut-systemd/dracut-pre-udev.sh55
-rw-r--r--modules.d/98dracut-systemd/dracut-shutdown-onfailure.service11
-rw-r--r--modules.d/98dracut-systemd/dracut-shutdown.service15
-rw-r--r--modules.d/98dracut-systemd/dracut-shutdown.service.8.asc53
-rw-r--r--modules.d/98dracut-systemd/dracut-tmpfiles.conf3
-rw-r--r--modules.d/98dracut-systemd/emergency.service29
-rwxr-xr-xmodules.d/98dracut-systemd/module-setup.sh58
-rwxr-xr-xmodules.d/98dracut-systemd/parse-root.sh38
-rwxr-xr-xmodules.d/98dracut-systemd/rootfs-generator.sh95
33 files changed, 1154 insertions, 0 deletions
diff --git a/modules.d/98dracut-systemd/dracut-cmdline-ask.service b/modules.d/98dracut-systemd/dracut-cmdline-ask.service
new file mode 100644
index 0000000..c9458b7
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-cmdline-ask.service
@@ -0,0 +1,32 @@
+# This file is part of dracut.
+
+[Unit]
+Description=dracut ask for additional cmdline parameters
+Documentation=man:dracut.bootup(7)
+DefaultDependencies=no
+Before=dracut-cmdline.service
+Wants=systemd-journald.socket
+After=systemd-journald.socket
+Wants=systemd-vconsole-setup.service
+After=systemd-vconsole-setup.service
+
+ConditionPathExists=/usr/lib/initrd-release
+ConditionKernelCommandLine=|rd.cmdline=ask
+ConditionPathExistsGlob=|/etc/cmdline.d/*.conf
+Conflicts=shutdown.target emergency.target
+
+[Service]
+Environment=DRACUT_SYSTEMD=1
+Environment=NEWROOT=/sysroot
+Type=oneshot
+ExecStart=-/bin/dracut-cmdline-ask
+StandardInput=tty
+StandardOutput=inherit
+StandardError=inherit
+RemainAfterExit=yes
+KillMode=process
+IgnoreSIGPIPE=no
+
+# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
+# terminates cleanly.
+KillSignal=SIGHUP
diff --git a/modules.d/98dracut-systemd/dracut-cmdline-ask.sh b/modules.d/98dracut-systemd/dracut-cmdline-ask.sh
new file mode 100755
index 0000000..13c4f20
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-cmdline-ask.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+getarg "rd.cmdline=ask" || exit 0
+
+sleep 0.5
+echo
+sleep 0.5
+echo
+sleep 0.5
+echo
+echo
+echo
+echo
+echo "Enter additional kernel command line parameter (end with ctrl-d or .)"
+while read -r -p "> " ${BASH:+-e} line || [ -n "$line" ]; do
+ [ "$line" = "." ] && break
+ [ -n "$line" ] && printf -- "%s\n" "$line" >> /etc/cmdline.d/99-cmdline-ask.conf
+done
+
+exit 0
diff --git a/modules.d/98dracut-systemd/dracut-cmdline.service b/modules.d/98dracut-systemd/dracut-cmdline.service
new file mode 100644
index 0000000..ed71d58
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-cmdline.service
@@ -0,0 +1,30 @@
+# This file is part of dracut.
+
+[Unit]
+Description=dracut cmdline hook
+Documentation=man:dracut-cmdline.service(8) man:dracut.bootup(7)
+DefaultDependencies=no
+Before=dracut-pre-udev.service
+After=systemd-journald.socket
+Wants=systemd-journald.socket
+ConditionPathExists=/usr/lib/initrd-release
+ConditionPathExistsGlob=|/etc/cmdline.d/*.conf
+ConditionDirectoryNotEmpty=|/lib/dracut/hooks/cmdline
+ConditionKernelCommandLine=|rd.break=cmdline
+ConditionKernelCommandLine=|resume
+ConditionKernelCommandLine=|noresume
+Conflicts=shutdown.target emergency.target
+
+[Service]
+Environment=DRACUT_SYSTEMD=1
+Environment=NEWROOT=/sysroot
+Type=oneshot
+ExecStart=-/bin/dracut-cmdline
+StandardInput=null
+StandardError=journal+console
+KillMode=process
+RemainAfterExit=yes
+
+# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
+# terminates cleanly.
+KillSignal=SIGHUP
diff --git a/modules.d/98dracut-systemd/dracut-cmdline.service.8.asc b/modules.d/98dracut-systemd/dracut-cmdline.service.8.asc
new file mode 100644
index 0000000..859448e
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-cmdline.service.8.asc
@@ -0,0 +1,26 @@
+DRACUT-CMDLINE.SERVICE(8)
+=========================
+:doctype: manpage
+:man source: dracut
+:man manual: dracut
+
+NAME
+----
+dracut-cmdline.service - runs the dracut hooks to parse the kernel command line
+
+SYNOPSIS
+--------
+dracut-cmdline.service
+
+DESCRIPTION
+-----------
+This service runs all the dracut hooks to parse the kernel command line in
+the initramfs.
+
+AUTHORS
+-------
+Harald Hoyer
+
+SEE ALSO
+--------
+*dracut.bootup*(7) *dracut*(8)
diff --git a/modules.d/98dracut-systemd/dracut-cmdline.sh b/modules.d/98dracut-systemd/dracut-cmdline.sh
new file mode 100755
index 0000000..646fead
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-cmdline.sh
@@ -0,0 +1,75 @@
+#!/bin/sh
+
+if [ -f /dracut-state.sh ]; then
+ . /dracut-state.sh 2> /dev/null
+fi
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+[ -f /usr/lib/initrd-release ] && . /usr/lib/initrd-release
+[ -n "$VERSION" ] && info "dracut-$VERSION"
+
+if ! getargbool 1 'rd.hostonly'; then
+ [ -f /etc/cmdline.d/99-cmdline-ask.conf ] && mv /etc/cmdline.d/99-cmdline-ask.conf /tmp/99-cmdline-ask.conf
+ remove_hostonly_files
+ systemctl --no-block daemon-reload
+ [ -f /tmp/99-cmdline-ask.conf ] && mv /tmp/99-cmdline-ask.conf /etc/cmdline.d/99-cmdline-ask.conf
+fi
+
+info "Using kernel command line parameters:" "$(getcmdline)"
+
+getargbool 0 rd.udev.log-priority=info -d rd.udev.info -d -n -y rdudevinfo && echo 'udev_log="info"' >> /etc/udev/udev.conf
+getargbool 0 rd.udev.log-priority=debug -d rd.udev.debug -d -n -y rdudevdebug && echo 'udev_log="debug"' >> /etc/udev/udev.conf
+
+source_conf /etc/conf.d
+
+# Get the "root=" parameter from the kernel command line, but differentiate
+# between the case where it was set to the empty string and the case where it
+# wasn't specified at all.
+if ! root="$(getarg root=)"; then
+ root_unset='UNSET'
+fi
+
+rflags="$(getarg rootflags=)"
+getargbool 0 ro && rflags="${rflags},ro"
+getargbool 0 rw && rflags="${rflags},rw"
+rflags="${rflags#,}"
+
+fstype="$(getarg rootfstype=)"
+if [ -z "$fstype" ]; then
+ fstype="auto"
+fi
+
+export root
+export rflags
+export fstype
+
+make_trace_mem "hook cmdline" '1+:mem' '1+:iomem' '3+:slab'
+# run scriptlets to parse the command line
+getarg 'rd.break=cmdline' -d 'rdbreak=cmdline' && emergency_shell -n cmdline "Break before cmdline"
+source_hook cmdline
+
+[ -f /lib/dracut/parse-resume.sh ] && . /lib/dracut/parse-resume.sh
+
+case "${root#block:}${root_unset}" in
+ LABEL=* | UUID=* | PARTUUID=* | PARTLABEL=*)
+ root="block:$(label_uuid_to_dev "${root#block:}")"
+ rootok=1
+ ;;
+ /dev/*)
+ root="block:${root#block:}"
+ rootok=1
+ ;;
+ UNSET | gpt-auto | tmpfs)
+ # systemd's gpt-auto-generator/fstab-generator handles this case.
+ rootok=1
+ ;;
+esac
+
+[ -z "${root}${root_unset}" ] && die "Empty root= argument"
+[ -z "$rootok" ] && die "Don't know how to handle 'root=$root'"
+
+export root rflags fstype netroot NEWROOT
+
+export -p > /dracut-state.sh
+
+exit 0
diff --git a/modules.d/98dracut-systemd/dracut-emergency.service b/modules.d/98dracut-systemd/dracut-emergency.service
new file mode 100644
index 0000000..eb3e67f
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-emergency.service
@@ -0,0 +1,28 @@
+# This file is part of dracut.
+
+[Unit]
+Description=Dracut Emergency Shell
+Documentation=man:dracut.bootup(7)
+DefaultDependencies=no
+After=systemd-vconsole-setup.service
+Wants=systemd-vconsole-setup.service
+Conflicts=shutdown.target emergency.target
+
+[Service]
+Environment=HOME=/
+Environment=DRACUT_SYSTEMD=1
+Environment=NEWROOT=/sysroot
+WorkingDirectory=/
+ExecStart=-/bin/dracut-emergency
+ExecStopPost=-/bin/rm -f -- /.console_lock
+Type=oneshot
+StandardInput=tty-force
+StandardOutput=inherit
+StandardError=inherit
+KillMode=process
+IgnoreSIGPIPE=no
+TasksMax=infinity
+
+# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
+# terminates cleanly.
+KillSignal=SIGHUP
diff --git a/modules.d/98dracut-systemd/dracut-emergency.sh b/modules.d/98dracut-systemd/dracut-emergency.sh
new file mode 100755
index 0000000..c6637a5
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-emergency.sh
@@ -0,0 +1,59 @@
+#!/bin/sh
+
+export DRACUT_SYSTEMD=1
+if [ -f /dracut-state.sh ]; then
+ . /dracut-state.sh 2> /dev/null
+fi
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+source_conf /etc/conf.d
+
+type plymouth > /dev/null 2>&1 && plymouth quit
+
+export _rdshell_name="dracut" action="Boot" hook="emergency"
+_emergency_action=$(getarg rd.emergency)
+
+if getargbool 1 rd.shell -d -y rdshell || getarg rd.break -d rdbreak; then
+ FSTXT="/run/dracut/fsck/fsck_help_$fstype.txt"
+ RDSOSREPORT="$(rdsosreport)"
+ source_hook "$hook"
+ while read -r _tty rest; do
+ (
+ echo
+ echo "$RDSOSREPORT"
+ echo
+ echo
+ echo 'Entering emergency mode. Exit the shell to continue.'
+ echo 'Type "journalctl" to view system logs.'
+ echo 'You might want to save "/run/initramfs/rdsosreport.txt" to a USB stick or /boot'
+ echo 'after mounting them and attach it to a bug report.'
+ echo
+ echo
+ [ -f "$FSTXT" ] && cat "$FSTXT"
+ ) > /dev/"$_tty"
+ done < /proc/consoles
+ [ -f /etc/profile ] && . /etc/profile
+ [ -z "$PS1" ] && export PS1="$_name:\${PWD}# "
+ exec sulogin -e
+else
+ export hook="shutdown-emergency"
+ warn "$action has failed. To debug this issue add \"rd.shell rd.debug\" to the kernel command line."
+ source_hook "$hook"
+ [ -z "$_emergency_action" ] && _emergency_action=halt
+fi
+
+/bin/rm -f -- /.console_lock
+
+case "$_emergency_action" in
+ reboot)
+ reboot || exit 1
+ ;;
+ poweroff)
+ poweroff || exit 1
+ ;;
+ halt)
+ halt || exit 1
+ ;;
+esac
+
+exit 0
diff --git a/modules.d/98dracut-systemd/dracut-initqueue.service b/modules.d/98dracut-systemd/dracut-initqueue.service
new file mode 100644
index 0000000..4cd32eb
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-initqueue.service
@@ -0,0 +1,28 @@
+# This file is part of dracut.
+
+[Unit]
+Description=dracut initqueue hook
+Documentation=man:dracut-initqueue.service(8) man:dracut.bootup(7)
+DefaultDependencies=no
+Before=remote-fs-pre.target
+Wants=remote-fs-pre.target
+After=systemd-udev-trigger.service
+Wants=systemd-udev-trigger.service
+ConditionPathExists=/usr/lib/initrd-release
+ConditionPathExists=|/lib/dracut/need-initqueue
+ConditionKernelCommandLine=|rd.break=initqueue
+Conflicts=shutdown.target emergency.target
+
+[Service]
+Environment=DRACUT_SYSTEMD=1
+Environment=NEWROOT=/sysroot
+Type=oneshot
+ExecStart=-/bin/dracut-initqueue
+StandardInput=null
+StandardError=journal+console
+KillMode=process
+RemainAfterExit=yes
+
+# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
+# terminates cleanly.
+KillSignal=SIGHUP
diff --git a/modules.d/98dracut-systemd/dracut-initqueue.service.8.asc b/modules.d/98dracut-systemd/dracut-initqueue.service.8.asc
new file mode 100644
index 0000000..66f2d33
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-initqueue.service.8.asc
@@ -0,0 +1,25 @@
+DRACUT-INITQUEUE.SERVICE(8)
+===========================
+:doctype: manpage
+:man source: dracut
+:man manual: dracut
+
+NAME
+----
+dracut-initqueue.service - runs the dracut main loop to find the real root
+
+SYNOPSIS
+--------
+dracut-initqueue.service
+
+DESCRIPTION
+-----------
+This service runs all the main loop of dracut in the initramfs to find the real root.
+
+AUTHORS
+-------
+Harald Hoyer
+
+SEE ALSO
+--------
+*dracut.bootup*(7) *dracut*(8)
diff --git a/modules.d/98dracut-systemd/dracut-initqueue.sh b/modules.d/98dracut-systemd/dracut-initqueue.sh
new file mode 100755
index 0000000..ce919ce
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-initqueue.sh
@@ -0,0 +1,95 @@
+#!/bin/sh
+
+export DRACUT_SYSTEMD=1
+if [ -f /dracut-state.sh ]; then
+ . /dracut-state.sh 2> /dev/null
+fi
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+source_conf /etc/conf.d
+
+make_trace_mem "hook initqueue" '1:shortmem' '2+:mem' '3+:slab'
+getarg 'rd.break=initqueue' -d 'rdbreak=initqueue' && emergency_shell -n initqueue "Break before initqueue"
+
+RDRETRY=$(getarg rd.retry -d 'rd_retry=')
+RDRETRY=${RDRETRY:-180}
+RDRETRY=$((RDRETRY * 2))
+export RDRETRY
+
+main_loop=0
+export main_loop
+
+while :; do
+
+ check_finished && break
+
+ udevadm settle --exit-if-exists="$hookdir"/initqueue/work
+
+ check_finished && break
+
+ if [ -f "$hookdir"/initqueue/work ]; then
+ rm -f -- "$hookdir/initqueue/work"
+ fi
+
+ for job in "$hookdir"/initqueue/*.sh; do
+ [ -e "$job" ] || break
+ # shellcheck disable=SC2097 disable=SC1090 disable=SC2098
+ job=$job . "$job"
+ check_finished && break 2
+ done
+
+ udevadm settle --timeout=0 > /dev/null 2>&1 || continue
+
+ for job in "$hookdir"/initqueue/settled/*.sh; do
+ [ -e "$job" ] || break
+ # shellcheck disable=SC2097 disable=SC1090 disable=SC2098
+ job=$job . "$job"
+ check_finished && break 2
+ done
+
+ udevadm settle --timeout=0 > /dev/null 2>&1 || continue
+
+ # no more udev jobs and queues empty.
+ sleep 0.5
+
+ for i in /run/systemd/ask-password/ask.*; do
+ [ -e "$i" ] && continue 2
+ done
+
+ if [ $main_loop -gt $((2 * RDRETRY / 3)) ]; then
+ warn "dracut-initqueue: timeout, still waiting for following initqueue hooks:"
+ for _f in "$hookdir"/initqueue/finished/*.sh; do
+ warn "$_f: \"$(cat "$_f")\""
+ done
+ if [ "$(ls -A "$hookdir"/initqueue/finished)" ]; then
+ warn "dracut-initqueue: starting timeout scripts"
+ for job in "$hookdir"/initqueue/timeout/*.sh; do
+ [ -e "$job" ] || break
+ # shellcheck disable=SC2097 disable=SC1090 disable=SC2098
+ job=$job . "$job"
+ udevadm settle --timeout=0 > /dev/null 2>&1 || main_loop=0
+ [ -f "$hookdir"/initqueue/work ] && main_loop=0
+ [ $main_loop -eq 0 ] && break
+ done
+ fi
+ fi
+
+ main_loop=$((main_loop + 1))
+ if [ $main_loop -gt $RDRETRY ]; then
+ if ! [ -f /sysroot/etc/fstab ] || ! [ -e /sysroot/sbin/init ]; then
+ emergency_shell "Could not boot."
+ fi
+ warn "Not all disks have been found."
+ warn "You might want to regenerate your initramfs."
+ break
+ fi
+done
+
+unset job
+unset queuetriggered
+unset main_loop
+unset RDRETRY
+
+export -p > /dracut-state.sh
+
+exit 0
diff --git a/modules.d/98dracut-systemd/dracut-mount.service b/modules.d/98dracut-systemd/dracut-mount.service
new file mode 100644
index 0000000..27fff82
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-mount.service
@@ -0,0 +1,26 @@
+# This file is part of dracut.
+
+[Unit]
+Description=dracut mount hook
+Documentation=man:dracut-mount.service(8) man:dracut.bootup(7)
+After=initrd-root-fs.target initrd-parse-etc.service
+After=dracut-initqueue.service dracut-pre-mount.service
+ConditionPathExists=/usr/lib/initrd-release
+ConditionDirectoryNotEmpty=|/lib/dracut/hooks/mount
+ConditionKernelCommandLine=|rd.break=mount
+DefaultDependencies=no
+Conflicts=shutdown.target emergency.target
+
+[Service]
+Environment=DRACUT_SYSTEMD=1
+Environment=NEWROOT=/sysroot
+Type=oneshot
+ExecStart=-/bin/dracut-mount
+StandardInput=null
+StandardError=journal+console
+KillMode=process
+RemainAfterExit=yes
+
+# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
+# terminates cleanly.
+KillSignal=SIGHUP
diff --git a/modules.d/98dracut-systemd/dracut-mount.service.8.asc b/modules.d/98dracut-systemd/dracut-mount.service.8.asc
new file mode 100644
index 0000000..969123f
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-mount.service.8.asc
@@ -0,0 +1,25 @@
+DRACUT-MOUNT.SERVICE(8)
+=======================
+:doctype: manpage
+:man source: dracut
+:man manual: dracut
+
+NAME
+----
+dracut-mount.service - runs the dracut hooks after /sysroot is mounted
+
+SYNOPSIS
+--------
+dracut-mount.service
+
+DESCRIPTION
+-----------
+This service runs all dracut hooks after the real root is mounted on /sysroot.
+
+AUTHORS
+-------
+Harald Hoyer
+
+SEE ALSO
+--------
+*dracut.bootup*(7) *dracut*(8)
diff --git a/modules.d/98dracut-systemd/dracut-mount.sh b/modules.d/98dracut-systemd/dracut-mount.sh
new file mode 100755
index 0000000..7892941
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-mount.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+export DRACUT_SYSTEMD=1
+if [ -f /dracut-state.sh ]; then
+ . /dracut-state.sh 2> /dev/null
+fi
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+source_conf /etc/conf.d
+
+make_trace_mem "hook mount" '1:shortmem' '2+:mem' '3+:slab'
+
+getarg 'rd.break=mount' -d 'rdbreak=mount' && emergency_shell -n mount "Break before mount"
+# mount scripts actually try to mount the root filesystem, and may
+# be sourced any number of times. As soon as one succeeds, no more are sourced.
+i=0
+while :; do
+ if ismounted "$NEWROOT"; then
+ usable_root "$NEWROOT" && break
+ umount "$NEWROOT"
+ fi
+ for f in "$hookdir"/mount/*.sh; do
+ # shellcheck disable=SC1090
+ [ -f "$f" ] && . "$f"
+ if ismounted "$NEWROOT"; then
+ usable_root "$NEWROOT" && break
+ warn "$NEWROOT has no proper rootfs layout, ignoring and removing offending mount hook"
+ umount "$NEWROOT"
+ rm -f -- "$f"
+ fi
+ done
+
+ i=$((i + 1))
+ [ $i -gt 20 ] && emergency_shell "Can't mount root filesystem"
+done
+
+export -p > /dracut-state.sh
+
+exit 0
diff --git a/modules.d/98dracut-systemd/dracut-pre-mount.service b/modules.d/98dracut-systemd/dracut-pre-mount.service
new file mode 100644
index 0000000..351370b
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-pre-mount.service
@@ -0,0 +1,26 @@
+# This file is part of dracut.
+
+[Unit]
+Description=dracut pre-mount hook
+Documentation=man:dracut-pre-mount.service(8) man:dracut.bootup(7)
+DefaultDependencies=no
+Before=initrd-root-fs.target sysroot.mount systemd-fsck-root.service
+After=dracut-initqueue.service cryptsetup.target
+ConditionPathExists=/usr/lib/initrd-release
+ConditionDirectoryNotEmpty=|/lib/dracut/hooks/pre-mount
+ConditionKernelCommandLine=|rd.break=pre-mount
+Conflicts=shutdown.target emergency.target
+
+[Service]
+Environment=DRACUT_SYSTEMD=1
+Environment=NEWROOT=/sysroot
+Type=oneshot
+ExecStart=-/bin/dracut-pre-mount
+StandardInput=null
+StandardError=journal+console
+KillMode=process
+RemainAfterExit=yes
+
+# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
+# terminates cleanly.
+KillSignal=SIGHUP
diff --git a/modules.d/98dracut-systemd/dracut-pre-mount.service.8.asc b/modules.d/98dracut-systemd/dracut-pre-mount.service.8.asc
new file mode 100644
index 0000000..9aa671a
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-pre-mount.service.8.asc
@@ -0,0 +1,25 @@
+DRACUT-PRE-MOUNT.SERVICE(8)
+===========================
+:doctype: manpage
+:man source: dracut
+:man manual: dracut
+
+NAME
+----
+dracut-pre-mount.service - runs the dracut hooks before /sysroot is mounted
+
+SYNOPSIS
+--------
+dracut-pre-mount.service
+
+DESCRIPTION
+-----------
+This service runs all dracut hooks before the real root is mounted on /sysroot.
+
+AUTHORS
+-------
+Harald Hoyer
+
+SEE ALSO
+--------
+*dracut.bootup*(7) *dracut*(8)
diff --git a/modules.d/98dracut-systemd/dracut-pre-mount.sh b/modules.d/98dracut-systemd/dracut-pre-mount.sh
new file mode 100755
index 0000000..ee51605
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-pre-mount.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+export DRACUT_SYSTEMD=1
+if [ -f /dracut-state.sh ]; then
+ . /dracut-state.sh 2> /dev/null
+fi
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+source_conf /etc/conf.d
+
+make_trace_mem "hook pre-mount" '1:shortmem' '2+:mem' '3+:slab'
+# pre pivot scripts are sourced just before we doing cleanup and switch over
+# to the new root.
+getarg 'rd.break=pre-mount' 'rdbreak=pre-mount' && emergency_shell -n pre-mount "Break before pre-mount"
+source_hook pre-mount
+
+export -p > /dracut-state.sh
+
+exit 0
diff --git a/modules.d/98dracut-systemd/dracut-pre-pivot.service b/modules.d/98dracut-systemd/dracut-pre-pivot.service
new file mode 100644
index 0000000..04a3705
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-pre-pivot.service
@@ -0,0 +1,35 @@
+# This file is part of dracut.
+
+[Unit]
+Description=dracut pre-pivot and cleanup hook
+Documentation=man:dracut-pre-pivot.service(8) man:dracut.bootup(7)
+DefaultDependencies=no
+After=initrd.target initrd-parse-etc.service sysroot.mount
+After=dracut-initqueue.service dracut-pre-mount.service dracut-mount.service
+Before=initrd-cleanup.service
+Wants=remote-fs.target
+After=remote-fs.target
+ConditionPathExists=/usr/lib/initrd-release
+ConditionDirectoryNotEmpty=|/lib/dracut/hooks/pre-pivot
+ConditionDirectoryNotEmpty=|/lib/dracut/hooks/cleanup
+ConditionKernelCommandLine=|rd.break=pre-pivot
+ConditionKernelCommandLine=|rd.break=cleanup
+ConditionKernelCommandLine=|rd.break
+ConditionPathExists=|/dev/root
+ConditionPathExists=|/dev/nfs
+Conflicts=shutdown.target emergency.target
+
+[Service]
+Environment=DRACUT_SYSTEMD=1
+Environment=NEWROOT=/sysroot
+Type=oneshot
+ExecStart=-/bin/dracut-pre-pivot
+StandardInput=null
+StandardError=journal+console
+KillMode=process
+RemainAfterExit=yes
+KeyringMode=shared
+
+# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
+# terminates cleanly.
+KillSignal=SIGHUP
diff --git a/modules.d/98dracut-systemd/dracut-pre-pivot.service.8.asc b/modules.d/98dracut-systemd/dracut-pre-pivot.service.8.asc
new file mode 100644
index 0000000..df500ac
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-pre-pivot.service.8.asc
@@ -0,0 +1,25 @@
+DRACUT-PRE-PIVOT.SERVICE(8)
+===========================
+:doctype: manpage
+:man source: dracut
+:man manual: dracut
+
+NAME
+----
+dracut-pre-pivot.service - runs the dracut hooks before switching root
+
+SYNOPSIS
+--------
+dracut-pre-pivot.service
+
+DESCRIPTION
+-----------
+This service runs all dracut hooks before the system switched to the real root.
+
+AUTHORS
+-------
+Harald Hoyer
+
+SEE ALSO
+--------
+*dracut.bootup*(7) *dracut*(8)
diff --git a/modules.d/98dracut-systemd/dracut-pre-pivot.sh b/modules.d/98dracut-systemd/dracut-pre-pivot.sh
new file mode 100755
index 0000000..8bf2325
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-pre-pivot.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+export DRACUT_SYSTEMD=1
+if [ -f /dracut-state.sh ]; then
+ . /dracut-state.sh 2> /dev/null
+fi
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+source_conf /etc/conf.d
+
+make_trace_mem "hook pre-pivot" '1:shortmem' '2+:mem' '3+:slab'
+# pre pivot scripts are sourced just before we doing cleanup and switch over
+# to the new root.
+getarg 'rd.break=pre-pivot' 'rdbreak=pre-pivot' && emergency_shell -n pre-pivot "Break before pre-pivot"
+source_hook pre-pivot
+
+# pre pivot cleanup scripts are sourced just before we switch over to the new root.
+getarg 'rd.break=cleanup' 'rdbreak=cleanup' && emergency_shell -n cleanup "Break before cleanup"
+source_hook cleanup
+
+_bv=$(getarg rd.break -d rdbreak) && [ -z "$_bv" ] \
+ && emergency_shell -n switch_root "Break before switch_root"
+unset _bv
+
+# remove helper symlink
+[ -h /dev/root ] && rm -f -- /dev/root
+[ -h /dev/nfs ] && rm -f -- /dev/nfs
+
+exit 0
diff --git a/modules.d/98dracut-systemd/dracut-pre-trigger.service b/modules.d/98dracut-systemd/dracut-pre-trigger.service
new file mode 100644
index 0000000..374cd3a
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-pre-trigger.service
@@ -0,0 +1,27 @@
+# This file is part of dracut.
+
+[Unit]
+Description=dracut pre-trigger hook
+Documentation=man:dracut-pre-trigger.service(8) man:dracut.bootup(7)
+DefaultDependencies=no
+Before=systemd-udev-trigger.service dracut-initqueue.service
+After=dracut-pre-udev.service systemd-udevd.service systemd-tmpfiles-setup-dev.service
+Wants=dracut-pre-udev.service systemd-udevd.service
+ConditionPathExists=/usr/lib/initrd-release
+ConditionDirectoryNotEmpty=|/lib/dracut/hooks/pre-trigger
+ConditionKernelCommandLine=|rd.break=pre-trigger
+Conflicts=shutdown.target emergency.target
+
+[Service]
+Environment=DRACUT_SYSTEMD=1
+Environment=NEWROOT=/sysroot
+Type=oneshot
+ExecStart=-/bin/dracut-pre-trigger
+StandardInput=null
+StandardError=journal+console
+KillMode=process
+RemainAfterExit=yes
+
+# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
+# terminates cleanly.
+KillSignal=SIGHUP
diff --git a/modules.d/98dracut-systemd/dracut-pre-trigger.service.8.asc b/modules.d/98dracut-systemd/dracut-pre-trigger.service.8.asc
new file mode 100644
index 0000000..5b0cc7f
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-pre-trigger.service.8.asc
@@ -0,0 +1,25 @@
+DRACUT-PRE-TRIGGER.SERVICE(8)
+=============================
+:doctype: manpage
+:man source: dracut
+:man manual: dracut
+
+NAME
+----
+dracut-pre-trigger.service - runs the dracut hooks before udevd is triggered
+
+SYNOPSIS
+--------
+dracut-pre-trigger.service
+
+DESCRIPTION
+-----------
+This service runs all dracut hooks before udevd is triggered in the initramfs.
+
+AUTHORS
+-------
+Harald Hoyer
+
+SEE ALSO
+--------
+*dracut.bootup*(7) *dracut*(8)
diff --git a/modules.d/98dracut-systemd/dracut-pre-trigger.sh b/modules.d/98dracut-systemd/dracut-pre-trigger.sh
new file mode 100755
index 0000000..dd0215e
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-pre-trigger.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+export DRACUT_SYSTEMD=1
+if [ -f /dracut-state.sh ]; then
+ . /dracut-state.sh 2> /dev/null
+fi
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+source_conf /etc/conf.d
+
+make_trace_mem "hook pre-trigger" '1:shortmem' '2+:mem' '3+:slab'
+
+source_hook pre-trigger
+
+getarg 'rd.break=pre-trigger' 'rdbreak=pre-trigger' && emergency_shell -n pre-trigger "Break before pre-trigger"
+
+udevadm control --reload > /dev/null 2>&1 || :
+
+export -p > /dracut-state.sh
+
+exit 0
diff --git a/modules.d/98dracut-systemd/dracut-pre-udev.service b/modules.d/98dracut-systemd/dracut-pre-udev.service
new file mode 100644
index 0000000..a61e9d4
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-pre-udev.service
@@ -0,0 +1,31 @@
+# This file is part of dracut.
+
+[Unit]
+Description=dracut pre-udev hook
+Documentation=man:dracut-pre-udev.service(8) man:dracut.bootup(7)
+DefaultDependencies=no
+Before=systemd-udevd.service dracut-pre-trigger.service
+After=dracut-cmdline.service
+Wants=dracut-cmdline.service
+ConditionPathExists=/usr/lib/initrd-release
+ConditionDirectoryNotEmpty=|/lib/dracut/hooks/pre-udev
+ConditionKernelCommandLine=|rd.break=pre-udev
+ConditionKernelCommandLine=|rd.driver.blacklist
+ConditionKernelCommandLine=|rd.driver.pre
+ConditionKernelCommandLine=|rd.driver.post
+ConditionPathExistsGlob=|/etc/cmdline.d/*.conf
+Conflicts=shutdown.target emergency.target
+
+[Service]
+Environment=DRACUT_SYSTEMD=1
+Environment=NEWROOT=/sysroot
+Type=oneshot
+ExecStart=-/bin/dracut-pre-udev
+StandardInput=null
+StandardError=journal+console
+KillMode=process
+RemainAfterExit=yes
+
+# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
+# terminates cleanly.
+KillSignal=SIGHUP
diff --git a/modules.d/98dracut-systemd/dracut-pre-udev.service.8.asc b/modules.d/98dracut-systemd/dracut-pre-udev.service.8.asc
new file mode 100644
index 0000000..c91c8e2
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-pre-udev.service.8.asc
@@ -0,0 +1,25 @@
+DRACUT-PRE-UDEV.SERVICE(8)
+==========================
+:doctype: manpage
+:man source: dracut
+:man manual: dracut
+
+NAME
+----
+dracut-pre-udev.service - runs the dracut hooks before udevd is started
+
+SYNOPSIS
+--------
+dracut-pre-udev.service
+
+DESCRIPTION
+-----------
+This service runs all dracut hooks before udevd is started in the initramfs.
+
+AUTHORS
+-------
+Harald Hoyer
+
+SEE ALSO
+--------
+*dracut.bootup*(7) *dracut*(8)
diff --git a/modules.d/98dracut-systemd/dracut-pre-udev.sh b/modules.d/98dracut-systemd/dracut-pre-udev.sh
new file mode 100755
index 0000000..feab32c
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-pre-udev.sh
@@ -0,0 +1,55 @@
+#!/bin/sh
+export DRACUT_SYSTEMD=1
+if [ -f /dracut-state.sh ]; then
+ . /dracut-state.sh 2> /dev/null
+fi
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+source_conf /etc/conf.d
+
+make_trace_mem "hook pre-udev" '1:shortmem' '2+:mem' '3+:slab'
+# pre pivot scripts are sourced just before we doing cleanup and switch over
+# to the new root.
+getarg 'rd.break=pre-udev' 'rdbreak=pre-udev' && emergency_shell -n pre-udev "Break before pre-udev"
+source_hook pre-udev
+
+_modprobe_d=/etc/modprobe.d
+if [ -d /usr/lib/modprobe.d ]; then
+ _modprobe_d=/usr/lib/modprobe.d
+elif [ -d /lib/modprobe.d ]; then
+ _modprobe_d=/lib/modprobe.d
+elif [ ! -d $_modprobe_d ]; then
+ mkdir -p $_modprobe_d
+fi
+
+for i in $(getargs rd.driver.pre -d rdloaddriver=); do
+ (
+ IFS=,
+ for p in $i; do
+ modprobe "$p" 2>&1 | vinfo
+ done
+ )
+done
+
+[ -d /etc/modprobe.d ] || mkdir -p /etc/modprobe.d
+
+for i in $(getargs rd.driver.blacklist -d rdblacklist=); do
+ (
+ IFS=,
+ for p in $i; do
+ echo "blacklist $p" >> $_modprobe_d/initramfsblacklist.conf
+ done
+ )
+done
+
+for p in $(getargs rd.driver.post -d rdinsmodpost=); do
+ echo "blacklist $p" >> $_modprobe_d/initramfsblacklist.conf
+ _do_insmodpost=1
+done
+
+[ -n "$_do_insmodpost" ] && initqueue --settled --unique --onetime insmodpost.sh
+unset _do_insmodpost _modprobe_d
+unset i
+
+export -p > /dracut-state.sh
+exit 0
diff --git a/modules.d/98dracut-systemd/dracut-shutdown-onfailure.service b/modules.d/98dracut-systemd/dracut-shutdown-onfailure.service
new file mode 100644
index 0000000..0570535
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-shutdown-onfailure.service
@@ -0,0 +1,11 @@
+# This file is part of dracut.
+
+[Unit]
+Description=Service executing upon dracut-shutdown failure to perform cleanup
+Documentation=man:dracut-shutdown.service(8)
+DefaultDependencies=no
+
+[Service]
+Type=oneshot
+ExecStart=-/bin/rm /run/initramfs/shutdown
+StandardError=null
diff --git a/modules.d/98dracut-systemd/dracut-shutdown.service b/modules.d/98dracut-systemd/dracut-shutdown.service
new file mode 100644
index 0000000..b2b704a
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-shutdown.service
@@ -0,0 +1,15 @@
+# This file is part of dracut.
+
+[Unit]
+Description=Restore /run/initramfs on shutdown
+Documentation=man:dracut-shutdown.service(8)
+After=local-fs.target boot.mount boot.automount
+Wants=local-fs.target
+ConditionPathExists=!/run/initramfs/bin/sh
+OnFailure=dracut-shutdown-onfailure.service
+
+[Service]
+RemainAfterExit=yes
+Type=oneshot
+ExecStart=/bin/true
+ExecStop=/usr/lib/dracut/dracut-initramfs-restore
diff --git a/modules.d/98dracut-systemd/dracut-shutdown.service.8.asc b/modules.d/98dracut-systemd/dracut-shutdown.service.8.asc
new file mode 100644
index 0000000..21ec88c
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-shutdown.service.8.asc
@@ -0,0 +1,53 @@
+DRACUT-SHUTDOWN.SERVICE(8)
+===========================
+:doctype: manpage
+:man source: dracut
+:man manual: dracut
+
+NAME
+----
+dracut-shutdown.service - unpack the initramfs to /run/initramfs
+
+SYNOPSIS
+--------
+dracut-shutdown.service
+
+DESCRIPTION
+-----------
+This service unpacks the initramfs image to /run/initramfs.
+systemd pivots into /run/initramfs at shutdown, so the root filesystem
+can be safely unmounted.
+
+The following steps are executed during a shutdown:
+
+* systemd switches to the shutdown.target
+* systemd starts /lib/systemd/system/shutdown.target.wants/dracut-shutdown.service
+* dracut-shutdown.service executes /usr/lib/dracut/dracut-initramfs-restore which unpacks the initramfs to /run/initramfs
+* systemd finishes shutdown.target
+* systemd kills all processes
+* systemd tries to unmount everything and mounts the remaining read-only
+* systemd checks, if there is a /run/initramfs/shutdown executable
+* if yes, it does a pivot_root to /run/initramfs and executes ./shutdown. The old root is then mounted on /oldroot. /usr/lib/dracut/modules.d/99shutdown/shutdown.sh is the shutdown executable.
+* shutdown will try to umount every /oldroot mount and calls the various shutdown hooks from the dracut modules
+
+This ensures, that all devices are disassembled and unmounted cleanly.
+
+To debug the shutdown process, you can get a shell in the shutdown procedure
+by injecting "rd.break=pre-shutdown rd.shell" or "rd.break=shutdown rd.shell".
+----
+# mkdir -p /run/initramfs/etc/cmdline.d
+# echo "rd.break=pre-shutdown rd.shell" > /run/initramfs/etc/cmdline.d/debug.conf
+# touch /run/initramfs/.need_shutdown
+----
+
+In case the unpack of the initramfs fails, dracut-shutdown-onfailure.service
+executes to make sure switch root doesn't happen, since it would result in
+switching to an incomplete initramfs.
+
+AUTHORS
+-------
+Harald Hoyer
+
+SEE ALSO
+--------
+*dracut*(8)
diff --git a/modules.d/98dracut-systemd/dracut-tmpfiles.conf b/modules.d/98dracut-systemd/dracut-tmpfiles.conf
new file mode 100644
index 0000000..3c21ce8
--- /dev/null
+++ b/modules.d/98dracut-systemd/dracut-tmpfiles.conf
@@ -0,0 +1,3 @@
+d /run/initramfs 0755 root root -
+d /run/initramfs/log 0755 root root -
+L /var/log - - - - ../run/initramfs/log
diff --git a/modules.d/98dracut-systemd/emergency.service b/modules.d/98dracut-systemd/emergency.service
new file mode 100644
index 0000000..27c69e1
--- /dev/null
+++ b/modules.d/98dracut-systemd/emergency.service
@@ -0,0 +1,29 @@
+# This file is part of dracut.
+
+[Unit]
+Description=Emergency Shell
+Documentation=man:dracut.bootup(7)
+DefaultDependencies=no
+After=systemd-vconsole-setup.service
+Wants=systemd-vconsole-setup.service
+Conflicts=shutdown.target
+Before=shutdown.target
+
+[Service]
+Environment=HOME=/
+Environment=DRACUT_SYSTEMD=1
+Environment=NEWROOT=/sysroot
+WorkingDirectory=/
+ExecStart=/bin/dracut-emergency
+ExecStopPost=-/usr/bin/systemctl --fail --no-block default
+Type=idle
+StandardInput=tty-force
+StandardOutput=inherit
+StandardError=inherit
+KillMode=process
+IgnoreSIGPIPE=no
+TasksMax=infinity
+
+# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
+# terminates cleanly.
+KillSignal=SIGHUP
diff --git a/modules.d/98dracut-systemd/module-setup.sh b/modules.d/98dracut-systemd/module-setup.sh
new file mode 100755
index 0000000..3195377
--- /dev/null
+++ b/modules.d/98dracut-systemd/module-setup.sh
@@ -0,0 +1,58 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ [[ $mount_needs ]] && return 1
+
+ return 0
+}
+
+# called by dracut
+depends() {
+ echo "systemd-initrd"
+ return 0
+}
+
+installkernel() {
+ return 0
+}
+
+# called by dracut
+install() {
+ inst_script "$moddir/dracut-emergency.sh" /bin/dracut-emergency
+ inst_simple "$moddir/emergency.service" "${systemdsystemunitdir}"/emergency.service
+ inst_simple "$moddir/dracut-emergency.service" "${systemdsystemunitdir}"/dracut-emergency.service
+ inst_simple "$moddir/emergency.service" "${systemdsystemunitdir}"/rescue.service
+
+ ln_r "${systemdsystemunitdir}/initrd.target" "${systemdsystemunitdir}/default.target"
+
+ inst_script "$moddir/dracut-cmdline.sh" /bin/dracut-cmdline
+ inst_script "$moddir/dracut-cmdline-ask.sh" /bin/dracut-cmdline-ask
+ inst_script "$moddir/dracut-pre-udev.sh" /bin/dracut-pre-udev
+ inst_script "$moddir/dracut-pre-trigger.sh" /bin/dracut-pre-trigger
+ inst_script "$moddir/dracut-initqueue.sh" /bin/dracut-initqueue
+ inst_script "$moddir/dracut-pre-mount.sh" /bin/dracut-pre-mount
+ inst_script "$moddir/dracut-mount.sh" /bin/dracut-mount
+ inst_script "$moddir/dracut-pre-pivot.sh" /bin/dracut-pre-pivot
+
+ inst_script "$moddir/rootfs-generator.sh" "$systemdutildir"/system-generators/dracut-rootfs-generator
+
+ inst_hook cmdline 00 "$moddir/parse-root.sh"
+
+ for i in \
+ dracut-cmdline.service \
+ dracut-cmdline-ask.service \
+ dracut-initqueue.service \
+ dracut-mount.service \
+ dracut-pre-mount.service \
+ dracut-pre-pivot.service \
+ dracut-pre-trigger.service \
+ dracut-pre-udev.service; do
+ inst_simple "$moddir/${i}" "$systemdsystemunitdir/${i}"
+ $SYSTEMCTL -q --root "$initdir" add-wants initrd.target "$i"
+ done
+
+ inst_simple "$moddir/dracut-tmpfiles.conf" "$tmpfilesdir/dracut-tmpfiles.conf"
+
+ inst_multiple sulogin
+}
diff --git a/modules.d/98dracut-systemd/parse-root.sh b/modules.d/98dracut-systemd/parse-root.sh
new file mode 100755
index 0000000..90f145a
--- /dev/null
+++ b/modules.d/98dracut-systemd/parse-root.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+root=$(getarg root=)
+case "${root#block:}" in
+ LABEL=* | UUID=* | PARTUUID=* | PARTLABEL=*)
+ root="block:$(label_uuid_to_dev "$root")"
+ rootok=1
+ ;;
+ /dev/nfs | /dev/root) # ignore legacy
+ ;;
+ /dev/*)
+ root="block:${root}"
+ rootok=1
+ ;;
+esac
+
+if [ "$rootok" = "1" ]; then
+ root_dev="${root#block:}"
+ root_name="$(str_replace "$root_dev" '/' '\x2f')"
+ if ! [ -e "$hookdir/initqueue/finished/devexists-${root_name}.sh" ]; then
+
+ # If a LUKS device needs unlocking via systemd in the initrd, assume
+ # it's for the root device. In that case, don't block on it if it's
+ # after remote-fs-pre.target since the initqueue is ordered before it so
+ # it will never actually show up (think Tang-pinned rootfs).
+ cat > "$hookdir/initqueue/finished/devexists-${root_name}.sh" << EOF
+if ! grep -q After=remote-fs-pre.target /run/systemd/generator/systemd-cryptsetup@*.service 2>/dev/null; then
+ [ -e "$root_dev" ]
+fi
+EOF
+ {
+ printf '[ -e "%s" ] || ' "$root_dev"
+ printf 'warn "\"%s\" does not exist"\n' "$root_dev"
+ } >> "$hookdir/emergency/80-${root_name}.sh"
+ fi
+fi
diff --git a/modules.d/98dracut-systemd/rootfs-generator.sh b/modules.d/98dracut-systemd/rootfs-generator.sh
new file mode 100755
index 0000000..cef3f49
--- /dev/null
+++ b/modules.d/98dracut-systemd/rootfs-generator.sh
@@ -0,0 +1,95 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+generator_wait_for_dev() {
+ local _name
+ local _timeout
+
+ _name=$(dev_unit_name "$1")
+ _timeout=$(getarg rd.timeout)
+ _timeout=${_timeout:-0}
+
+ if ! [ -L "$GENERATOR_DIR"/initrd.target.wants/"${_name}".device ]; then
+ [ -d "$GENERATOR_DIR"/initrd.target.wants ] || mkdir -p "$GENERATOR_DIR"/initrd.target.wants
+ ln -s ../"${_name}".device "$GENERATOR_DIR"/initrd.target.wants/"${_name}".device
+ fi
+
+ if ! [ -f "$GENERATOR_DIR"/"${_name}".device.d/timeout.conf ]; then
+ mkdir -p "$GENERATOR_DIR"/"${_name}".device.d
+ {
+ echo "[Unit]"
+ echo "JobTimeoutSec=$_timeout"
+ echo "JobRunningTimeoutSec=$_timeout"
+ } > "$GENERATOR_DIR"/"${_name}".device.d/timeout.conf
+ fi
+}
+
+generator_mount_rootfs() {
+ local _type="$2"
+ local _flags="$3"
+ local _name
+
+ [ -z "$1" ] && return 0
+
+ _name=$(dev_unit_name "$1")
+ if ! [ -f "$GENERATOR_DIR"/sysroot.mount ]; then
+ {
+ echo "[Unit]"
+ echo "Before=initrd-root-fs.target"
+ echo "Requires=systemd-fsck@${_name}.service"
+ echo "After=systemd-fsck@${_name}.service"
+ echo "[Mount]"
+ echo "Where=/sysroot"
+ echo "What=$1"
+ echo "Options=${_flags}"
+ echo "Type=${_type}"
+ } > "$GENERATOR_DIR"/sysroot.mount
+ fi
+ if ! [ -L "$GENERATOR_DIR"/initrd-root-fs.target.requires/sysroot.mount ]; then
+ [ -d "$GENERATOR_DIR"/initrd-root-fs.target.requires ] || mkdir -p "$GENERATOR_DIR"/initrd-root-fs.target.requires
+ ln -s ../sysroot.mount "$GENERATOR_DIR"/initrd-root-fs.target.requires/sysroot.mount
+ fi
+}
+
+generator_fsck_after_pre_mount() {
+ local _name
+
+ [ -z "$1" ] && return 0
+
+ _name=$(dev_unit_name "$1")
+ [ -d "$GENERATOR_DIR"/systemd-fsck@"${_name}".service.d ] || mkdir -p "$GENERATOR_DIR"/systemd-fsck@"${_name}".service.d
+ if ! [ -f "$GENERATOR_DIR"/systemd-fsck@"${_name}".service.d/after-pre-mount.conf ]; then
+ {
+ echo "[Unit]"
+ echo "After=dracut-pre-mount.service"
+ } > "$GENERATOR_DIR"/systemd-fsck@"${_name}".service.d/after-pre-mount.conf
+ fi
+
+}
+
+root=$(getarg root=)
+case "${root#block:}" in
+ LABEL=* | UUID=* | PARTUUID=* | PARTLABEL=*)
+ root="block:$(label_uuid_to_dev "$root")"
+ rootok=1
+ ;;
+ /dev/nfs) # ignore legacy /dev/nfs
+ ;;
+ /dev/*)
+ root="block:${root}"
+ rootok=1
+ ;;
+esac
+
+if [ "$rootok" = "1" ]; then
+ GENERATOR_DIR="$1"
+ [ -z "$GENERATOR_DIR" ] && exit 1
+ [ -d "$GENERATOR_DIR" ] || mkdir -p "$GENERATOR_DIR"
+
+ generator_wait_for_dev "${root#block:}"
+ generator_fsck_after_pre_mount "${root#block:}"
+ strstr "$(cat /proc/cmdline)" 'root=' || generator_mount_rootfs "${root#block:}" "$(getarg rootfstype=)" "$(getarg rootflags=)"
+fi
+
+exit 0