summaryrefslogtreecommitdiffstats
path: root/modules.d
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
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 '')
-rwxr-xr-xmodules.d/00bash/module-setup.sh32
-rwxr-xr-xmodules.d/00dash/module-setup.sh32
-rwxr-xr-xmodules.d/00mksh/module-setup.sh34
-rwxr-xr-xmodules.d/00systemd-network-management/module-setup.sh21
-rwxr-xr-xmodules.d/00systemd/module-setup.sh267
-rwxr-xr-xmodules.d/00warpclock/module-setup.sh39
-rwxr-xr-xmodules.d/00warpclock/warpclock.sh14
-rwxr-xr-xmodules.d/01fips/fips-boot.sh16
-rwxr-xr-xmodules.d/01fips/fips-load-crypto.sh14
-rwxr-xr-xmodules.d/01fips/fips-noboot.sh15
-rwxr-xr-xmodules.d/01fips/fips.sh195
-rwxr-xr-xmodules.d/01fips/module-setup.sh85
-rw-r--r--modules.d/01systemd-ac-power/99-initrd-power-targets.rules3
-rw-r--r--modules.d/01systemd-ac-power/initrd-on-ac-power.target8
-rw-r--r--modules.d/01systemd-ac-power/initrd-on-battery-power.target8
-rwxr-xr-xmodules.d/01systemd-ac-power/module-setup.sh29
-rwxr-xr-xmodules.d/01systemd-ask-password/module-setup.sh60
-rwxr-xr-xmodules.d/01systemd-coredump/module-setup.sh55
-rwxr-xr-xmodules.d/01systemd-creds/module-setup.sh46
-rw-r--r--modules.d/01systemd-hostnamed/99-systemd-networkd-dracut.conf6
-rwxr-xr-xmodules.d/01systemd-hostnamed/module-setup.sh52
-rw-r--r--modules.d/01systemd-hostnamed/org.freedesktop.hostname1_dracut.conf19
-rw-r--r--modules.d/01systemd-hostnamed/systemd-hostname-dracut.conf2
-rwxr-xr-xmodules.d/01systemd-initrd/module-setup.sh34
-rwxr-xr-xmodules.d/01systemd-integritysetup/module-setup.sh59
-rw-r--r--modules.d/01systemd-journald/initrd.conf9
-rwxr-xr-xmodules.d/01systemd-journald/module-setup.sh72
-rwxr-xr-xmodules.d/01systemd-ldconfig/module-setup.sh49
-rwxr-xr-xmodules.d/01systemd-modules-load/module-setup.sh44
-rwxr-xr-xmodules.d/01systemd-networkd/module-setup.sh87
-rwxr-xr-xmodules.d/01systemd-pcrphase/module-setup.sh43
-rwxr-xr-xmodules.d/01systemd-portabled/module-setup.sh82
-rwxr-xr-xmodules.d/01systemd-pstore/module-setup.sh53
-rwxr-xr-xmodules.d/01systemd-repart/module-setup.sh40
-rwxr-xr-xmodules.d/01systemd-resolved/module-setup.sh58
-rw-r--r--modules.d/01systemd-resolved/resolved-tmpfile-dracut.conf2
-rwxr-xr-xmodules.d/01systemd-sysctl/module-setup.sh47
-rwxr-xr-xmodules.d/01systemd-sysext/module-setup.sh47
-rwxr-xr-xmodules.d/01systemd-sysusers/module-setup.sh45
-rw-r--r--modules.d/01systemd-sysusers/sysusers-dracut.conf2
-rwxr-xr-xmodules.d/01systemd-timedated/module-setup.sh46
-rwxr-xr-xmodules.d/01systemd-timesyncd/module-setup.sh67
-rw-r--r--modules.d/01systemd-timesyncd/timesyncd-tmpfile-dracut.conf2
-rwxr-xr-xmodules.d/01systemd-tmpfiles/module-setup.sh71
-rwxr-xr-xmodules.d/01systemd-udevd/module-setup.sh112
-rwxr-xr-xmodules.d/01systemd-veritysetup/module-setup.sh60
-rw-r--r--modules.d/02caps/README33
-rwxr-xr-xmodules.d/02caps/caps.sh34
-rwxr-xr-xmodules.d/02caps/module-setup.sh25
-rwxr-xr-xmodules.d/03modsign/load-modsign-keys.sh11
-rwxr-xr-xmodules.d/03modsign/module-setup.sh38
-rwxr-xr-xmodules.d/03rescue/module-setup.sh19
-rwxr-xr-xmodules.d/04watchdog-modules/module-setup.sh41
-rwxr-xr-xmodules.d/04watchdog/module-setup.sh34
-rwxr-xr-xmodules.d/04watchdog/watchdog-stop.sh2
-rwxr-xr-xmodules.d/04watchdog/watchdog.sh12
-rwxr-xr-xmodules.d/05busybox/module-setup.sh31
-rwxr-xr-xmodules.d/06dbus-broker/module-setup.sh93
-rwxr-xr-xmodules.d/06dbus-daemon/module-setup.sh96
-rwxr-xr-xmodules.d/06rngd/module-setup.sh40
-rw-r--r--modules.d/06rngd/rngd.service8
-rwxr-xr-xmodules.d/09dbus/module-setup.sh31
-rw-r--r--modules.d/10i18n/10-console.rules2
-rw-r--r--modules.d/10i18n/README124
-rwxr-xr-xmodules.d/10i18n/console_init.sh89
-rwxr-xr-xmodules.d/10i18n/module-setup.sh297
-rwxr-xr-xmodules.d/10i18n/parse-i18n.sh36
-rwxr-xr-xmodules.d/30convertfs/convertfs.sh193
-rwxr-xr-xmodules.d/30convertfs/do-convertfs.sh9
-rwxr-xr-xmodules.d/30convertfs/module-setup.sh19
-rwxr-xr-xmodules.d/35connman/cm-config.sh24
-rw-r--r--modules.d/35connman/cm-initrd.service24
-rwxr-xr-xmodules.d/35connman/cm-lib.sh12
-rwxr-xr-xmodules.d/35connman/cm-run.sh15
-rw-r--r--modules.d/35connman/cm-wait-online-initrd.service16
-rwxr-xr-xmodules.d/35connman/module-setup.sh47
-rwxr-xr-xmodules.d/35connman/netroot.sh92
-rwxr-xr-xmodules.d/35network-legacy/dhclient-script.sh275
-rw-r--r--modules.d/35network-legacy/dhclient.conf11
-rwxr-xr-xmodules.d/35network-legacy/dhcp-multi.sh133
-rwxr-xr-xmodules.d/35network-legacy/ifup.sh563
-rwxr-xr-xmodules.d/35network-legacy/kill-dhclient.sh15
-rwxr-xr-xmodules.d/35network-legacy/module-setup.sh99
-rwxr-xr-xmodules.d/35network-legacy/net-genrules.sh125
-rwxr-xr-xmodules.d/35network-legacy/parse-bond.sh76
-rwxr-xr-xmodules.d/35network-legacy/parse-bridge.sh49
-rwxr-xr-xmodules.d/35network-legacy/parse-ibft.sh10
-rwxr-xr-xmodules.d/35network-legacy/parse-ifname.sh24
-rwxr-xr-xmodules.d/35network-legacy/parse-ip-opts.sh151
-rwxr-xr-xmodules.d/35network-legacy/parse-team.sh66
-rwxr-xr-xmodules.d/35network-legacy/parse-vlan.sh37
-rw-r--r--modules.d/35network-manager/initrd-no-auto-default.conf5
-rwxr-xr-xmodules.d/35network-manager/module-setup.sh84
-rwxr-xr-xmodules.d/35network-manager/nm-config.sh35
-rw-r--r--modules.d/35network-manager/nm-initrd.service31
-rwxr-xr-xmodules.d/35network-manager/nm-lib.sh34
-rwxr-xr-xmodules.d/35network-manager/nm-run.sh68
-rw-r--r--modules.d/35network-manager/nm-wait-online-initrd.service16
-rwxr-xr-xmodules.d/40network/dhcp-root.sh30
-rwxr-xr-xmodules.d/40network/ifname-genrules.sh32
-rwxr-xr-xmodules.d/40network/module-setup.sh48
-rwxr-xr-xmodules.d/40network/net-lib.sh906
-rwxr-xr-xmodules.d/40network/netroot.sh92
-rwxr-xr-xmodules.d/45ifcfg/module-setup.sh19
-rwxr-xr-xmodules.d/45ifcfg/write-ifcfg.sh311
-rwxr-xr-xmodules.d/45url-lib/module-setup.sh88
-rwxr-xr-xmodules.d/45url-lib/url-lib.sh174
-rwxr-xr-xmodules.d/50drm/module-setup.sh59
-rwxr-xr-xmodules.d/50plymouth/module-setup.sh53
-rwxr-xr-xmodules.d/50plymouth/plymouth-emergency.sh3
-rwxr-xr-xmodules.d/50plymouth/plymouth-newroot.sh5
-rwxr-xr-xmodules.d/50plymouth/plymouth-populate-initrd.sh45
-rwxr-xr-xmodules.d/50plymouth/plymouth-pretrigger.sh27
-rwxr-xr-xmodules.d/62bluetooth/module-setup.sh93
-rwxr-xr-xmodules.d/80cms/cms-write-ifcfg.sh105
-rwxr-xr-xmodules.d/80cms/cmsifup.sh43
-rwxr-xr-xmodules.d/80cms/cmssetup.sh221
-rwxr-xr-xmodules.d/80cms/module-setup.sh36
-rw-r--r--modules.d/80lvmmerge/README.md61
-rwxr-xr-xmodules.d/80lvmmerge/lvmmerge.sh95
-rwxr-xr-xmodules.d/80lvmmerge/module-setup.sh25
-rwxr-xr-xmodules.d/80lvmthinpool-monitor/module-setup.sh24
-rw-r--r--modules.d/80lvmthinpool-monitor/start-thinpool-monitor.service14
-rwxr-xr-xmodules.d/80lvmthinpool-monitor/start-thinpool-monitor.sh47
-rwxr-xr-xmodules.d/80test-makeroot/finished-false.sh2
-rwxr-xr-xmodules.d/80test-makeroot/module-setup.sh19
-rwxr-xr-xmodules.d/80test-root/module-setup.sh27
-rwxr-xr-xmodules.d/80test/hard-off.sh3
-rwxr-xr-xmodules.d/80test/module-setup.sh16
-rwxr-xr-xmodules.d/81cio_ignore/module-setup.sh41
-rwxr-xr-xmodules.d/81cio_ignore/parse-cio_accept.sh23
-rw-r--r--modules.d/90btrfs/80-btrfs.rules8
-rwxr-xr-xmodules.d/90btrfs/btrfs_device_ready.sh18
-rwxr-xr-xmodules.d/90btrfs/btrfs_finished.sh21
-rwxr-xr-xmodules.d/90btrfs/btrfs_timeout.sh6
-rwxr-xr-xmodules.d/90btrfs/module-setup.sh60
-rwxr-xr-xmodules.d/90crypt/crypt-cleanup.sh14
-rwxr-xr-xmodules.d/90crypt/crypt-lib.sh278
-rwxr-xr-xmodules.d/90crypt/crypt-run-generator.sh31
-rwxr-xr-xmodules.d/90crypt/cryptroot-ask.sh207
-rwxr-xr-xmodules.d/90crypt/module-setup.sh186
-rwxr-xr-xmodules.d/90crypt/parse-crypt.sh197
-rwxr-xr-xmodules.d/90crypt/parse-keydev.sh44
-rwxr-xr-xmodules.d/90crypt/probe-keydev.sh16
-rw-r--r--modules.d/90dm/11-dm.rules5
-rw-r--r--modules.d/90dm/59-persistent-storage-dm.rules15
-rwxr-xr-xmodules.d/90dm/dm-pre-udev.sh4
-rwxr-xr-xmodules.d/90dm/dm-shutdown.sh53
-rwxr-xr-xmodules.d/90dm/module-setup.sh38
-rw-r--r--modules.d/90dmraid/61-dmraid-imsm.rules28
-rwxr-xr-xmodules.d/90dmraid/dmraid.sh46
-rwxr-xr-xmodules.d/90dmraid/module-setup.sh87
-rwxr-xr-xmodules.d/90dmraid/parse-dm.sh27
-rwxr-xr-xmodules.d/90dmsquash-live-autooverlay/create-overlay-genrules.sh9
-rwxr-xr-xmodules.d/90dmsquash-live-autooverlay/create-overlay.sh119
-rwxr-xr-xmodules.d/90dmsquash-live-autooverlay/module-setup.sh24
-rwxr-xr-xmodules.d/90dmsquash-live-ntfs/module-setup.sh21
-rwxr-xr-xmodules.d/90dmsquash-live-ntfs/mount-ntfs-3g.sh20
-rwxr-xr-xmodules.d/90dmsquash-live/apply-live-updates.sh22
-rw-r--r--modules.d/90dmsquash-live/checkisomd5@.service14
-rwxr-xr-xmodules.d/90dmsquash-live/dmsquash-generator.sh80
-rwxr-xr-xmodules.d/90dmsquash-live/dmsquash-live-genrules.sh18
-rwxr-xr-xmodules.d/90dmsquash-live/dmsquash-live-root.sh432
-rwxr-xr-xmodules.d/90dmsquash-live/dmsquash-liveiso-genrules.sh9
-rwxr-xr-xmodules.d/90dmsquash-live/iso-scan.sh38
-rwxr-xr-xmodules.d/90dmsquash-live/module-setup.sh39
-rwxr-xr-xmodules.d/90dmsquash-live/parse-dmsquash-live.sh57
-rwxr-xr-xmodules.d/90dmsquash-live/parse-iso-scan.sh9
-rwxr-xr-xmodules.d/90kernel-modules-extra/module-setup.sh186
-rwxr-xr-xmodules.d/90kernel-modules/insmodpost.sh12
-rwxr-xr-xmodules.d/90kernel-modules/module-setup.sh154
-rwxr-xr-xmodules.d/90kernel-modules/parse-kernel.sh38
-rwxr-xr-xmodules.d/90kernel-network-modules/module-setup.sh50
-rwxr-xr-xmodules.d/90livenet/fetch-liveupdate.sh31
-rwxr-xr-xmodules.d/90livenet/livenet-generator.sh84
-rwxr-xr-xmodules.d/90livenet/livenetroot.sh60
-rwxr-xr-xmodules.d/90livenet/module-setup.sh24
-rwxr-xr-xmodules.d/90livenet/parse-livenet.sh33
-rw-r--r--modules.d/90lvm/64-lvm.rules29
-rwxr-xr-xmodules.d/90lvm/lvm_scan.sh176
-rwxr-xr-xmodules.d/90lvm/module-setup.sh117
-rwxr-xr-xmodules.d/90lvm/parse-lvm.sh17
-rw-r--r--modules.d/90mdraid/59-persistent-storage-md.rules24
-rw-r--r--modules.d/90mdraid/65-md-incremental-imsm.rules44
-rwxr-xr-xmodules.d/90mdraid/md-shutdown.sh23
-rwxr-xr-xmodules.d/90mdraid/mdmon-pre-shutdown.sh13
-rwxr-xr-xmodules.d/90mdraid/mdmon-pre-udev.sh4
-rwxr-xr-xmodules.d/90mdraid/mdraid-cleanup.sh21
-rwxr-xr-xmodules.d/90mdraid/mdraid-needshutdown.sh9
-rwxr-xr-xmodules.d/90mdraid/mdraid-waitclean.sh24
-rwxr-xr-xmodules.d/90mdraid/mdraid_start.sh70
-rwxr-xr-xmodules.d/90mdraid/module-setup.sh139
-rwxr-xr-xmodules.d/90mdraid/parse-md.sh64
-rwxr-xr-xmodules.d/90multipath/module-setup.sh154
-rwxr-xr-xmodules.d/90multipath/multipath-shutdown.sh7
-rw-r--r--modules.d/90multipath/multipathd-configure.service21
-rwxr-xr-xmodules.d/90multipath/multipathd-needshutdown.sh10
-rwxr-xr-xmodules.d/90multipath/multipathd-stop.sh15
-rw-r--r--modules.d/90multipath/multipathd.service27
-rwxr-xr-xmodules.d/90multipath/multipathd.sh17
-rwxr-xr-xmodules.d/90nvdimm/module-setup.sh32
-rwxr-xr-xmodules.d/90overlayfs/module-setup.sh19
-rwxr-xr-xmodules.d/90overlayfs/mount-overlayfs.sh20
-rwxr-xr-xmodules.d/90overlayfs/prepare-overlayfs.sh21
-rwxr-xr-xmodules.d/90ppcmac/load-thermal.sh30
-rwxr-xr-xmodules.d/90ppcmac/module-setup.sh83
-rwxr-xr-xmodules.d/90qemu-net/module-setup.sh21
-rwxr-xr-xmodules.d/90qemu/module-setup.sh23
-rw-r--r--modules.d/91crypt-gpg/README50
-rwxr-xr-xmodules.d/91crypt-gpg/crypt-gpg-lib.sh68
-rwxr-xr-xmodules.d/91crypt-gpg/module-setup.sh73
-rwxr-xr-xmodules.d/91crypt-loop/crypt-loop-lib.sh40
-rwxr-xr-xmodules.d/91crypt-loop/module-setup.sh25
-rwxr-xr-xmodules.d/91fido2/module-setup.sh30
-rwxr-xr-xmodules.d/91pcsc/module-setup.sh62
-rw-r--r--modules.d/91pcsc/pcscd.service13
-rw-r--r--modules.d/91pcsc/pcscd.socket11
-rwxr-xr-xmodules.d/91pkcs11/module-setup.sh35
-rwxr-xr-xmodules.d/91tpm2-tss/module-setup.sh59
-rwxr-xr-xmodules.d/91zipl/install_zipl_cmdline.sh39
-rwxr-xr-xmodules.d/91zipl/module-setup.sh67
-rwxr-xr-xmodules.d/91zipl/parse-zipl.sh51
-rwxr-xr-xmodules.d/95cifs/cifs-lib.sh38
-rwxr-xr-xmodules.d/95cifs/cifsroot.sh22
-rwxr-xr-xmodules.d/95cifs/module-setup.sh58
-rwxr-xr-xmodules.d/95cifs/parse-cifsroot.sh51
-rwxr-xr-xmodules.d/95dasd/module-setup.sh27
-rwxr-xr-xmodules.d/95dasd/parse-dasd.sh11
-rwxr-xr-xmodules.d/95dasd_mod/module-setup.sh27
-rwxr-xr-xmodules.d/95dasd_mod/parse-dasd-mod.sh18
-rwxr-xr-xmodules.d/95dasd_rules/module-setup.sh65
-rwxr-xr-xmodules.d/95dasd_rules/parse-dasd.sh43
-rwxr-xr-xmodules.d/95dcssblk/module-setup.sh34
-rwxr-xr-xmodules.d/95dcssblk/parse-dcssblk.sh6
-rwxr-xr-xmodules.d/95debug/module-setup.sh22
-rwxr-xr-xmodules.d/95fcoe-uefi/module-setup.sh27
-rwxr-xr-xmodules.d/95fcoe-uefi/parse-uefifcoe.sh33
-rwxr-xr-xmodules.d/95fcoe/cleanup-fcoe.sh15
-rwxr-xr-xmodules.d/95fcoe/fcoe-edd.sh54
-rwxr-xr-xmodules.d/95fcoe/fcoe-up.sh106
-rwxr-xr-xmodules.d/95fcoe/lldpad.sh19
-rwxr-xr-xmodules.d/95fcoe/module-setup.sh122
-rwxr-xr-xmodules.d/95fcoe/parse-fcoe.sh106
-rwxr-xr-xmodules.d/95fcoe/stop-fcoe.sh6
-rwxr-xr-xmodules.d/95fstab-sys/module-setup.sh17
-rwxr-xr-xmodules.d/95fstab-sys/mount-sys.sh39
-rwxr-xr-xmodules.d/95iscsi/cleanup-iscsi.sh5
-rwxr-xr-xmodules.d/95iscsi/iscsiroot.sh322
-rwxr-xr-xmodules.d/95iscsi/module-setup.sh294
-rwxr-xr-xmodules.d/95iscsi/mount-lun.sh15
-rwxr-xr-xmodules.d/95iscsi/parse-iscsiroot.sh156
-rwxr-xr-xmodules.d/95lunmask/fc_transport_scan_lun.sh26
-rwxr-xr-xmodules.d/95lunmask/module-setup.sh73
-rwxr-xr-xmodules.d/95lunmask/parse-lunmask.sh40
-rwxr-xr-xmodules.d/95lunmask/sas_transport_scan_lun.sh26
-rwxr-xr-xmodules.d/95nbd/module-setup.sh39
-rwxr-xr-xmodules.d/95nbd/nbd-generator.sh64
-rwxr-xr-xmodules.d/95nbd/nbdroot.sh137
-rwxr-xr-xmodules.d/95nbd/parse-nbdroot.sh64
-rwxr-xr-xmodules.d/95nfs/module-setup.sh138
-rwxr-xr-xmodules.d/95nfs/nfs-lib.sh157
-rwxr-xr-xmodules.d/95nfs/nfs-start-rpc.sh23
-rwxr-xr-xmodules.d/95nfs/nfsroot-cleanup.sh29
-rwxr-xr-xmodules.d/95nfs/nfsroot.sh30
-rwxr-xr-xmodules.d/95nfs/parse-nfsroot.sh128
-rw-r--r--modules.d/95nvmf/95-nvmf-initqueue.rules10
-rwxr-xr-xmodules.d/95nvmf/module-setup.sh148
-rwxr-xr-xmodules.d/95nvmf/nbftroot.sh5
-rwxr-xr-xmodules.d/95nvmf/nvmf-autoconnect.sh54
-rwxr-xr-xmodules.d/95nvmf/parse-nvmf-boot-connections.sh326
-rwxr-xr-xmodules.d/95qeth_rules/module-setup.sh58
-rwxr-xr-xmodules.d/95resume/module-setup.sh68
-rwxr-xr-xmodules.d/95resume/parse-resume.sh81
-rwxr-xr-xmodules.d/95resume/resume.sh18
-rwxr-xr-xmodules.d/95rootfs-block/block-genrules.sh16
-rwxr-xr-xmodules.d/95rootfs-block/module-setup.sh92
-rwxr-xr-xmodules.d/95rootfs-block/mount-root.sh135
-rwxr-xr-xmodules.d/95rootfs-block/parse-block.sh15
-rwxr-xr-xmodules.d/95rootfs-block/rootfallback.sh22
-rwxr-xr-xmodules.d/95ssh-client/module-setup.sh80
-rwxr-xr-xmodules.d/95terminfo/module-setup.sh17
-rw-r--r--modules.d/95udev-rules/59-persistent-storage.rules9
-rw-r--r--modules.d/95udev-rules/61-persistent-storage.rules22
-rwxr-xr-xmodules.d/95udev-rules/module-setup.sh83
-rwxr-xr-xmodules.d/95virtfs/module-setup.sh31
-rwxr-xr-xmodules.d/95virtfs/mount-virtfs.sh74
-rwxr-xr-xmodules.d/95virtfs/parse-virtfs.sh8
-rwxr-xr-xmodules.d/95virtiofs/module-setup.sh31
-rwxr-xr-xmodules.d/95virtiofs/mount-virtiofs.sh20
-rwxr-xr-xmodules.d/95virtiofs/parse-virtiofs.sh9
-rwxr-xr-xmodules.d/95zfcp/module-setup.sh34
-rwxr-xr-xmodules.d/95zfcp/parse-zfcp.sh16
-rwxr-xr-xmodules.d/95zfcp_rules/module-setup.sh80
-rwxr-xr-xmodules.d/95zfcp_rules/parse-zfcp.sh73
-rwxr-xr-xmodules.d/95znet/module-setup.sh29
-rwxr-xr-xmodules.d/95znet/parse-ccw.sh25
-rwxr-xr-xmodules.d/96securityfs/module-setup.sh16
-rwxr-xr-xmodules.d/96securityfs/securityfs.sh8
-rwxr-xr-xmodules.d/97biosdevname/module-setup.sh19
-rwxr-xr-xmodules.d/97biosdevname/parse-biosdevname.sh10
-rw-r--r--modules.d/97masterkey/README68
-rwxr-xr-xmodules.d/97masterkey/masterkey.sh69
-rwxr-xr-xmodules.d/97masterkey/module-setup.sh26
-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
-rw-r--r--modules.d/98ecryptfs/README50
-rwxr-xr-xmodules.d/98ecryptfs/ecryptfs-mount.sh95
-rwxr-xr-xmodules.d/98ecryptfs/module-setup.sh22
-rw-r--r--modules.d/98integrity/README68
-rwxr-xr-xmodules.d/98integrity/evm-enable.sh169
-rwxr-xr-xmodules.d/98integrity/ima-keys-load.sh60
-rwxr-xr-xmodules.d/98integrity/ima-policy-load.sh40
-rwxr-xr-xmodules.d/98integrity/module-setup.sh20
-rwxr-xr-xmodules.d/98pollcdrom/module-setup.sh16
-rwxr-xr-xmodules.d/98pollcdrom/pollcdrom.sh21
-rwxr-xr-xmodules.d/98selinux/module-setup.sh17
-rwxr-xr-xmodules.d/98selinux/selinux-loadpolicy.sh70
-rw-r--r--modules.d/98syslog/README24
-rwxr-xr-xmodules.d/98syslog/module-setup.sh38
-rwxr-xr-xmodules.d/98syslog/parse-syslog-opts.sh38
-rw-r--r--modules.d/98syslog/rsyslog.conf31
-rwxr-xr-xmodules.d/98syslog/rsyslogd-start.sh47
-rwxr-xr-xmodules.d/98syslog/rsyslogd-stop.sh13
-rwxr-xr-xmodules.d/98syslog/syslog-cleanup.sh14
-rwxr-xr-xmodules.d/98usrmount/module-setup.sh20
-rwxr-xr-xmodules.d/98usrmount/mount-usr.sh110
-rwxr-xr-xmodules.d/99base/dracut-dev-lib.sh139
-rwxr-xr-xmodules.d/99base/dracut-lib.sh1178
-rwxr-xr-xmodules.d/99base/init.sh399
-rwxr-xr-xmodules.d/99base/initqueue.sh72
-rwxr-xr-xmodules.d/99base/loginit.sh23
-rwxr-xr-xmodules.d/99base/module-setup.sh146
-rwxr-xr-xmodules.d/99base/parse-root-opts.sh14
-rwxr-xr-xmodules.d/99base/rdsosreport.sh61
-rwxr-xr-xmodules.d/99fs-lib/fs-lib.sh262
-rwxr-xr-xmodules.d/99fs-lib/module-setup.sh89
-rwxr-xr-xmodules.d/99img-lib/img-lib.sh108
-rwxr-xr-xmodules.d/99img-lib/module-setup.sh21
-rwxr-xr-xmodules.d/99memstrack/memstrack-report.sh17
-rwxr-xr-xmodules.d/99memstrack/memstrack-start.sh65
-rw-r--r--modules.d/99memstrack/memstrack.service15
-rwxr-xr-xmodules.d/99memstrack/module-setup.sh28
-rwxr-xr-xmodules.d/99shutdown/module-setup.sh26
-rwxr-xr-xmodules.d/99shutdown/shutdown.sh176
-rwxr-xr-xmodules.d/99squash/init-squash.sh34
-rwxr-xr-xmodules.d/99squash/module-setup.sh68
-rwxr-xr-xmodules.d/99uefi-lib/module-setup.sh17
-rwxr-xr-xmodules.d/99uefi-lib/uefi-lib.sh162
379 files changed, 23187 insertions, 0 deletions
diff --git a/modules.d/00bash/module-setup.sh b/modules.d/00bash/module-setup.sh
new file mode 100755
index 0000000..89ef654
--- /dev/null
+++ b/modules.d/00bash/module-setup.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed.
+ require_binaries bash || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+
+ inst /bin/bash
+
+ # Prefer bash as default shell if no other shell is preferred.
+ [[ -L $initdir/bin/sh ]] || ln -sf bash "${initdir}/bin/sh"
+
+}
diff --git a/modules.d/00dash/module-setup.sh b/modules.d/00dash/module-setup.sh
new file mode 100755
index 0000000..4a0c0e7
--- /dev/null
+++ b/modules.d/00dash/module-setup.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed.
+ require_binaries dash || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+
+ inst /bin/dash
+
+ # Prefer dash as default shell if no other shell is preferred.
+ [[ -L $initdir/bin/sh ]] || ln -sf dash "${initdir}/bin/sh"
+
+}
diff --git a/modules.d/00mksh/module-setup.sh b/modules.d/00mksh/module-setup.sh
new file mode 100755
index 0000000..8942b42
--- /dev/null
+++ b/modules.d/00mksh/module-setup.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed.
+ require_binaries mksh || return 1
+ require_binaries printf || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+
+ inst /bin/mksh
+ inst printf
+
+ # Prefer mksh as default shell if no other shell is preferred.
+ [[ -L $initdir/bin/sh ]] || ln -sf mksh "${initdir}/bin/sh"
+
+}
diff --git a/modules.d/00systemd-network-management/module-setup.sh b/modules.d/00systemd-network-management/module-setup.sh
new file mode 100755
index 0000000..f8ba351
--- /dev/null
+++ b/modules.d/00systemd-network-management/module-setup.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # This module has external dependency on other module(s).
+ echo systemd systemd-hostnamed systemd-networkd systemd-resolved systemd-timedated systemd-timesyncd
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
diff --git a/modules.d/00systemd/module-setup.sh b/modules.d/00systemd/module-setup.sh
new file mode 100755
index 0000000..9a13a1d
--- /dev/null
+++ b/modules.d/00systemd/module-setup.sh
@@ -0,0 +1,267 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+ [[ $mount_needs ]] && return 1
+ # If the binary(s) requirements are not fulfilled the module can't be installed
+ require_binaries "$systemdutildir"/systemd || return 1
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+installkernel() {
+ hostonly='' instmods autofs4 ipv6 algif_hash hmac sha256
+ instmods -s efivarfs
+}
+
+# called by dracut
+install() {
+ local _mods
+
+ if [[ $prefix == /run/* ]]; then
+ dfatal 'systemd does not work with a prefix, which contains "/run"!!'
+ exit 1
+ fi
+
+ inst_multiple -o \
+ "$systemdutildir"/systemd \
+ "$systemdutildir"/systemd-coredump \
+ "$systemdutildir"/systemd-cgroups-agent \
+ "$systemdutildir"/systemd-executor \
+ "$systemdutildir"/systemd-shutdown \
+ "$systemdutildir"/systemd-reply-password \
+ "$systemdutildir"/systemd-fsck \
+ "$systemdutildir"/systemd-udevd \
+ "$systemdutildir"/systemd-journald \
+ "$systemdutildir"/systemd-sysctl \
+ "$systemdutildir"/systemd-modules-load \
+ "$systemdutildir"/systemd-vconsole-setup \
+ "$systemdutildir"/systemd-volatile-root \
+ "$systemdutildir"/systemd-sysroot-fstab-check \
+ "$systemdutildir"/system-generators/systemd-debug-generator \
+ "$systemdutildir"/system-generators/systemd-fstab-generator \
+ "$systemdutildir"/system-generators/systemd-gpt-auto-generator \
+ "$systemdsystemunitdir"/debug-shell.service \
+ "$systemdsystemunitdir"/cryptsetup.target \
+ "$systemdsystemunitdir"/cryptsetup-pre.target \
+ "$systemdsystemunitdir"/remote-cryptsetup.target \
+ "$systemdsystemunitdir"/emergency.target \
+ "$systemdsystemunitdir"/sysinit.target \
+ "$systemdsystemunitdir"/basic.target \
+ "$systemdsystemunitdir"/halt.target \
+ "$systemdsystemunitdir"/kexec.target \
+ "$systemdsystemunitdir"/local-fs.target \
+ "$systemdsystemunitdir"/local-fs-pre.target \
+ "$systemdsystemunitdir"/remote-fs.target \
+ "$systemdsystemunitdir"/remote-fs-pre.target \
+ "$systemdsystemunitdir"/multi-user.target \
+ "$systemdsystemunitdir"/network.target \
+ "$systemdsystemunitdir"/network-pre.target \
+ "$systemdsystemunitdir"/network-online.target \
+ "$systemdsystemunitdir"/nss-lookup.target \
+ "$systemdsystemunitdir"/nss-user-lookup.target \
+ "$systemdsystemunitdir"/poweroff.target \
+ "$systemdsystemunitdir"/reboot.target \
+ "$systemdsystemunitdir"/rescue.target \
+ "$systemdsystemunitdir"/rpcbind.target \
+ "$systemdsystemunitdir"/shutdown.target \
+ "$systemdsystemunitdir"/final.target \
+ "$systemdsystemunitdir"/sigpwr.target \
+ "$systemdsystemunitdir"/sockets.target \
+ "$systemdsystemunitdir"/swap.target \
+ "$systemdsystemunitdir"/timers.target \
+ "$systemdsystemunitdir"/paths.target \
+ "$systemdsystemunitdir"/umount.target \
+ "$systemdsystemunitdir"/sys-kernel-config.mount \
+ "$systemdsystemunitdir"/modprobe@.service \
+ "$systemdsystemunitdir"/kmod-static-nodes.service \
+ "$systemdsystemunitdir"/systemd-tmpfiles-setup.service \
+ "$systemdsystemunitdir"/systemd-tmpfiles-setup-dev.service \
+ "$systemdsystemunitdir"/systemd-tmpfiles-setup-dev-early.service \
+ "$systemdsystemunitdir"/systemd-ask-password-console.path \
+ "$systemdsystemunitdir"/systemd-udevd-control.socket \
+ "$systemdsystemunitdir"/systemd-udevd-kernel.socket \
+ "$systemdsystemunitdir"/systemd-ask-password-plymouth.path \
+ "$systemdsystemunitdir"/systemd-journald.socket \
+ "$systemdsystemunitdir"/systemd-journald-audit.socket \
+ "$systemdsystemunitdir"/systemd-ask-password-console.service \
+ "$systemdsystemunitdir"/systemd-modules-load.service \
+ "$systemdsystemunitdir"/systemd-halt.service \
+ "$systemdsystemunitdir"/systemd-poweroff.service \
+ "$systemdsystemunitdir"/systemd-reboot.service \
+ "$systemdsystemunitdir"/systemd-kexec.service \
+ "$systemdsystemunitdir"/systemd-fsck@.service \
+ "$systemdsystemunitdir"/systemd-udevd.service \
+ "$systemdsystemunitdir"/systemd-udev-trigger.service \
+ "$systemdsystemunitdir"/systemd-udev-settle.service \
+ "$systemdsystemunitdir"/systemd-ask-password-plymouth.service \
+ "$systemdsystemunitdir"/systemd-journald.service \
+ "$systemdsystemunitdir"/systemd-vconsole-setup.service \
+ "$systemdsystemunitdir"/systemd-volatile-root.service \
+ "$systemdsystemunitdir"/systemd-sysctl.service \
+ "$systemdsystemunitdir"/sysinit.target.wants/systemd-modules-load.service \
+ "$systemdsystemunitdir"/sysinit.target.wants/systemd-ask-password-console.path \
+ "$systemdsystemunitdir"/sysinit.target.wants/systemd-journald.service \
+ "$systemdsystemunitdir"/sockets.target.wants/systemd-udevd-control.socket \
+ "$systemdsystemunitdir"/sockets.target.wants/systemd-udevd-kernel.socket \
+ "$systemdsystemunitdir"/sockets.target.wants/systemd-journald.socket \
+ "$systemdsystemunitdir"/sockets.target.wants/systemd-journald-audit.socket \
+ "$systemdsystemunitdir"/sockets.target.wants/systemd-journald-dev-log.socket \
+ "$systemdsystemunitdir"/sysinit.target.wants/systemd-udevd.service \
+ "$systemdsystemunitdir"/sysinit.target.wants/systemd-udev-trigger.service \
+ "$systemdsystemunitdir"/sysinit.target.wants/kmod-static-nodes.service \
+ "$systemdsystemunitdir"/sysinit.target.wants/systemd-tmpfiles-setup.service \
+ "$systemdsystemunitdir"/sysinit.target.wants/systemd-tmpfiles-setup-dev.service \
+ "$systemdsystemunitdir"/sysinit.target.wants/systemd-tmpfiles-setup-dev-early.service \
+ "$systemdsystemunitdir"/sysinit.target.wants/systemd-sysctl.service \
+ "$systemdsystemunitdir"/ctrl-alt-del.target \
+ "$systemdsystemunitdir"/reboot.target \
+ "$systemdsystemunitdir"/systemd-reboot.service \
+ "$systemdsystemunitdir"/syslog.socket \
+ "$systemdsystemunitdir"/slices.target \
+ "$systemdsystemunitdir"/system.slice \
+ "$systemdsystemunitdir"/-.slice \
+ "$tmpfilesdir"/systemd.conf \
+ journalctl systemctl \
+ echo swapoff \
+ kmod insmod rmmod modprobe modinfo depmod lsmod \
+ mount umount reboot poweroff \
+ systemd-run systemd-escape \
+ systemd-cgls systemd-tmpfiles \
+ systemd-ask-password systemd-tty-ask-password-agent \
+ /etc/udev/udev.hwdb
+
+ inst_multiple -o \
+ /usr/lib/modules-load.d/*.conf \
+ /usr/lib/sysctl.d/*.conf
+
+ modules_load_get() {
+ local _line i
+ for i in "$dracutsysrootdir$1"/*.conf; do
+ [[ -f $i ]] || continue
+ while read -r _line || [ -n "$_line" ]; do
+ case $_line in
+ \#*) ;;
+
+ \;*) ;;
+
+ *)
+ echo "$_line"
+ ;;
+ esac
+ done < "$i"
+ done
+ }
+
+ mapfile -t _mods < <(modules_load_get /usr/lib/modules-load.d)
+ [[ ${#_mods[@]} -gt 0 ]] && hostonly='' instmods "${_mods[@]}"
+
+ if [[ $hostonly ]]; then
+ inst_multiple -H -o \
+ /etc/systemd/journald.conf \
+ /etc/systemd/journald.conf.d/*.conf \
+ /etc/systemd/system.conf \
+ /etc/systemd/system.conf.d/*.conf \
+ "$systemdsystemconfdir"/modprobe@.service \
+ "$systemdsystemconfdir/modprobe@.service.d/*.conf" \
+ /etc/hosts \
+ /etc/hostname \
+ /etc/nsswitch.conf \
+ /etc/machine-id \
+ /etc/machine-info \
+ /etc/vconsole.conf \
+ /etc/locale.conf \
+ /etc/modules-load.d/*.conf \
+ /etc/sysctl.d/*.conf \
+ /etc/sysctl.conf \
+ /etc/udev/udev.conf
+
+ mapfile -t _mods < <(modules_load_get /etc/modules-load.d)
+ [[ ${#_mods[@]} -gt 0 ]] && hostonly='' instmods "${_mods[@]}"
+ fi
+
+ if ! [[ -e "$initdir/etc/machine-id" ]]; then
+ : > "$initdir/etc/machine-id"
+ chmod 444 "$initdir/etc/machine-id"
+ fi
+
+ # install adm user/group for journald
+ inst_multiple nologin
+ {
+ grep '^systemd-journal:' "$dracutsysrootdir"/etc/passwd 2> /dev/null
+ grep '^adm:' "$dracutsysrootdir"/etc/passwd 2> /dev/null
+ # we don't use systemd-networkd, but the user is in systemd.conf tmpfiles snippet
+ grep '^systemd-network:' "$dracutsysrootdir"/etc/passwd 2> /dev/null
+ } >> "$initdir/etc/passwd"
+
+ {
+ grep '^systemd-journal:' "$dracutsysrootdir"/etc/group 2> /dev/null
+ grep '^wheel:' "$dracutsysrootdir"/etc/group 2> /dev/null
+ grep '^adm:' "$dracutsysrootdir"/etc/group 2> /dev/null
+ grep '^utmp:' "$dracutsysrootdir"/etc/group 2> /dev/null
+ grep '^root:' "$dracutsysrootdir"/etc/group 2> /dev/null
+ # we don't use systemd-networkd, but the user is in systemd.conf tmpfiles snippet
+ grep '^systemd-network:' "$dracutsysrootdir"/etc/group 2> /dev/null
+ } >> "$initdir/etc/group"
+
+ local _systemdbinary="$systemdutildir"/systemd
+
+ if ldd "$_systemdbinary" | grep -qw libasan; then
+ local _wrapper="$systemdutildir"/systemd-asan-wrapper
+ cat > "$initdir"/"$_wrapper" << EOF
+#!/bin/sh
+mount -t proc -o nosuid,nodev,noexec proc /proc
+exec $_systemdbinary
+EOF
+ chmod 755 "$initdir"/"$_wrapper"
+ _systemdbinary="$_wrapper"
+ unset _wrapper
+ fi
+ ln_r "$_systemdbinary" "/init"
+ ln_r "$_systemdbinary" "/sbin/init"
+
+ unset _systemdbinary
+
+ inst_binary true
+ ln_r "$(find_binary true)" "/usr/bin/loginctl"
+ ln_r "$(find_binary true)" "/bin/loginctl"
+ inst_rules \
+ 70-uaccess.rules \
+ 71-seat.rules \
+ 73-seat-late.rules \
+ 90-vconsole.rules \
+ 99-systemd.rules
+
+ for i in \
+ emergency.target \
+ rescue.target \
+ systemd-ask-password-console.service \
+ systemd-ask-password-plymouth.service; do
+ [[ -f "$systemdsystemunitdir"/$i ]] || continue
+ $SYSTEMCTL -q --root "$initdir" add-wants "$i" systemd-vconsole-setup.service
+ done
+
+ mkdir -p "$initdir/etc/systemd"
+ # We must use a volatile journal, and we don't want rate-limiting
+ {
+ echo "[Journal]"
+ echo "Storage=volatile"
+ echo "RateLimitInterval=0"
+ echo "RateLimitBurst=0"
+ } >> "$initdir/etc/systemd/journald.conf"
+
+ $SYSTEMCTL -q --root "$initdir" set-default multi-user.target
+
+ # Install library file(s)
+ _arch=${DRACUT_ARCH:-$(uname -m)}
+ inst_libdir_file \
+ {"tls/$_arch/",tls/,"$_arch/",}"libnss_*"
+
+}
diff --git a/modules.d/00warpclock/module-setup.sh b/modules.d/00warpclock/module-setup.sh
new file mode 100755
index 0000000..44aa177
--- /dev/null
+++ b/modules.d/00warpclock/module-setup.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # hwclock does not exist on S390(x), bail out silently then
+ local _arch=${DRACUT_ARCH:-$(uname -m)}
+ [ "$_arch" = "s390" -o "$_arch" = "s390x" ] && return 1
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed.
+ require_binaries hwclock || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+
+ inst_hook pre-trigger 00 "$moddir/warpclock.sh"
+
+ inst_multiple -o \
+ /usr/share/zoneinfo/UTC \
+ /etc/localtime \
+ /etc/adjtime \
+ hwclock
+
+}
diff --git a/modules.d/00warpclock/warpclock.sh b/modules.d/00warpclock/warpclock.sh
new file mode 100755
index 0000000..fb4df0b
--- /dev/null
+++ b/modules.d/00warpclock/warpclock.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+# This file is part of dracut warpclock module.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Set the kernel's timezone and reset the system time
+# if adjtime is set to LOCAL.
+
+if test -e /etc/adjtime; then
+ while read -r line; do
+ if test "$line" = LOCAL; then
+ hwclock --systz
+ fi
+ done < /etc/adjtime
+fi
diff --git a/modules.d/01fips/fips-boot.sh b/modules.d/01fips/fips-boot.sh
new file mode 100755
index 0000000..34760e0
--- /dev/null
+++ b/modules.d/01fips/fips-boot.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+if ! fipsmode=$(getarg fips) || [ "$fipsmode" = "0" ]; then
+ rm -f -- /etc/modprobe.d/fips.conf > /dev/null 2>&1
+elif [ -z "$fipsmode" ]; then
+ die "FIPS mode have to be enabled by 'fips=1' not just 'fips'"
+elif getarg boot= > /dev/null; then
+ . /sbin/fips.sh
+ fips_info "fips-boot: start"
+ if mount_boot; then
+ do_fips || die "FIPS integrity test failed"
+ fi
+ fips_info "fips-boot: done!"
+fi
diff --git a/modules.d/01fips/fips-load-crypto.sh b/modules.d/01fips/fips-load-crypto.sh
new file mode 100755
index 0000000..6ef42b9
--- /dev/null
+++ b/modules.d/01fips/fips-load-crypto.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+if ! fipsmode=$(getarg fips) || [ "$fipsmode" = "0" ]; then
+ rm -f -- /etc/modprobe.d/fips.conf > /dev/null 2>&1
+elif [ -z "$fipsmode" ]; then
+ die "FIPS mode have to be enabled by 'fips=1' not just 'fips'"
+else
+ . /sbin/fips.sh
+ fips_info "fips-load-crypto: start"
+ fips_load_crypto || die "FIPS integrity test failed"
+ fips_info "fips-load-crypto: done!"
+fi
diff --git a/modules.d/01fips/fips-noboot.sh b/modules.d/01fips/fips-noboot.sh
new file mode 100755
index 0000000..963a034
--- /dev/null
+++ b/modules.d/01fips/fips-noboot.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+if ! fipsmode=$(getarg fips) || [ "$fipsmode" = "0" ]; then
+ rm -f -- /etc/modprobe.d/fips.conf > /dev/null 2>&1
+elif [ -z "$fipsmode" ]; then
+ die "FIPS mode have to be enabled by 'fips=1' not just 'fips'"
+elif ! [ -f /tmp/fipsdone ]; then
+ . /sbin/fips.sh
+ fips_info "fips-noboot: start"
+ mount_boot
+ do_fips || die "FIPS integrity test failed"
+ fips_info "fips-noboot: done!"
+fi
diff --git a/modules.d/01fips/fips.sh b/modules.d/01fips/fips.sh
new file mode 100755
index 0000000..2e7b7cb
--- /dev/null
+++ b/modules.d/01fips/fips.sh
@@ -0,0 +1,195 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+# systemd lets stdout go to journal only, but the system
+# has to halt when the integrity check fails to satisfy FIPS.
+if [ -z "$DRACUT_SYSTEMD" ]; then
+ fips_info() {
+ info "$*"
+ }
+else
+ fips_info() {
+ echo "$*" >&2
+ }
+fi
+
+mount_boot() {
+ boot=$(getarg boot=)
+
+ if [ -n "$boot" ]; then
+ if [ -d /boot ] && ismounted /boot; then
+ boot_dev=
+ if command -v findmnt > /dev/null; then
+ boot_dev=$(findmnt -n -o SOURCE /boot)
+ fi
+ fips_info "Ignoring 'boot=$boot' as /boot is already mounted ${boot_dev:+"from '$boot_dev'"}"
+ return 0
+ fi
+
+ case "$boot" in
+ LABEL=* | UUID=* | PARTUUID=* | PARTLABEL=*)
+ boot="$(label_uuid_to_dev "$boot")"
+ ;;
+ /dev/*) ;;
+
+ *)
+ die "You have to specify boot=<boot device> as a boot option for fips=1"
+ ;;
+ esac
+
+ if ! [ -e "$boot" ]; then
+ udevadm trigger --action=add > /dev/null 2>&1
+
+ i=0
+ while ! [ -e "$boot" ]; do
+ udevadm settle --exit-if-exists="$boot"
+ [ -e "$boot" ] && break
+ sleep 0.5
+ i=$((i + 1))
+ [ $i -gt 40 ] && break
+ done
+ fi
+
+ [ -e "$boot" ] || return 1
+
+ mkdir -p /boot
+ fips_info "Mounting $boot as /boot"
+ mount -oro "$boot" /boot || return 1
+ FIPS_MOUNTED_BOOT=1
+ elif ! ismounted /boot && [ -d "$NEWROOT/boot" ]; then
+ # shellcheck disable=SC2114
+ rm -fr -- /boot
+ ln -sf "$NEWROOT/boot" /boot
+ else
+ die "You have to specify boot=<boot device> as a boot option for fips=1"
+ fi
+}
+
+do_rhevh_check() {
+ KERNEL=$(uname -r)
+ kpath=${1}
+
+ # If we're on RHEV-H, the kernel is in /run/initramfs/live/vmlinuz0
+ HMAC_SUM_ORIG=$(while read -r a _ || [ -n "$a" ]; do printf "%s\n" "$a"; done < "$NEWROOT/boot/.vmlinuz-${KERNEL}.hmac")
+ HMAC_SUM_CALC=$(sha512hmac "$kpath" | while read -r a _ || [ -n "$a" ]; do printf "%s\n" "$a"; done || return 1)
+ if [ -z "$HMAC_SUM_ORIG" ] || [ -z "$HMAC_SUM_CALC" ] || [ "${HMAC_SUM_ORIG}" != "${HMAC_SUM_CALC}" ]; then
+ warn "HMAC sum mismatch"
+ return 1
+ fi
+ fips_info "rhevh_check OK"
+ return 0
+}
+
+nonfatal_modprobe() {
+ modprobe "$1" 2>&1 > /dev/stdout \
+ | while read -r line || [ -n "$line" ]; do
+ echo "${line#modprobe: FATAL: }" >&2
+ done
+}
+
+fips_load_crypto() {
+ local _k
+ local _v
+ local _module
+ local _found
+
+ read -d '' -r FIPSMODULES < /etc/fipsmodules
+
+ fips_info "Loading and integrity checking all crypto modules"
+ mv /etc/modprobe.d/fips.conf /etc/modprobe.d/fips.conf.bak
+ for _module in $FIPSMODULES; do
+ if [ "$_module" != "tcrypt" ]; then
+ if ! nonfatal_modprobe "${_module}" 2> /tmp/fips.modprobe_err; then
+ # check if kernel provides generic algo
+ _found=0
+ while read -r _k _ _v || [ -n "$_k" ]; do
+ [ "$_k" != "name" -a "$_k" != "driver" ] && continue
+ [ "$_v" != "$_module" ] && continue
+ _found=1
+ break
+ done < /proc/crypto
+ [ "$_found" = "0" ] && cat /tmp/fips.modprobe_err >&2 && return 1
+ fi
+ fi
+ done
+ mv /etc/modprobe.d/fips.conf.bak /etc/modprobe.d/fips.conf
+
+ fips_info "Self testing crypto algorithms"
+ modprobe tcrypt || return 1
+ rmmod tcrypt
+}
+
+do_fips() {
+ KERNEL=$(uname -r)
+
+ if ! getarg rd.fips.skipkernel > /dev/null; then
+
+ fips_info "Checking integrity of kernel"
+ if [ -e "/run/initramfs/live/vmlinuz0" ]; then
+ do_rhevh_check /run/initramfs/live/vmlinuz0 || return 1
+ elif [ -e "/run/initramfs/live/isolinux/vmlinuz0" ]; then
+ do_rhevh_check /run/initramfs/live/isolinux/vmlinuz0 || return 1
+ elif [ -e "/run/install/repo/images/pxeboot/vmlinuz" ]; then
+ # This is a boot.iso with the .hmac inside the install.img
+ do_rhevh_check /run/install/repo/images/pxeboot/vmlinuz || return 1
+ else
+ BOOT_IMAGE="$(getarg BOOT_IMAGE)"
+
+ # On s390x, BOOT_IMAGE isn't a path but an integer representing the
+ # entry number selected. Let's try the root of /boot first, and
+ # otherwise fallback to trying to parse the BLS entries if it's a
+ # BLS-based system.
+ if [ "$(uname -m)" = s390x ]; then
+ if [ -e "/boot/vmlinuz-${KERNEL}" ]; then
+ BOOT_IMAGE="vmlinuz-${KERNEL}"
+ elif [ -d /boot/loader/entries ]; then
+ bls=$(find /boot/loader/entries -name '*.conf' | sort -rV | sed -n "$((BOOT_IMAGE + 1))p")
+ if [ -e "${bls}" ]; then
+ BOOT_IMAGE=$(grep ^linux "${bls}" | cut -d' ' -f2)
+ fi
+ fi
+ fi
+
+ # Trim off any leading GRUB boot device (e.g. ($root) )
+ BOOT_IMAGE="$(echo "${BOOT_IMAGE}" | sed 's/^(.*)//')"
+
+ BOOT_IMAGE_NAME="${BOOT_IMAGE##*/}"
+ BOOT_IMAGE_PATH="${BOOT_IMAGE%"${BOOT_IMAGE_NAME}"}"
+
+ if [ -z "$BOOT_IMAGE_NAME" ]; then
+ BOOT_IMAGE_NAME="vmlinuz-${KERNEL}"
+ elif ! [ -e "/boot/${BOOT_IMAGE_PATH}/${BOOT_IMAGE_NAME}" ]; then
+ #if /boot is not a separate partition BOOT_IMAGE might start with /boot
+ BOOT_IMAGE_PATH=${BOOT_IMAGE_PATH#"/boot"}
+ #on some architectures BOOT_IMAGE does not contain path to kernel
+ #so if we can't find anything, let's treat it in the same way as if it was empty
+ if ! [ -e "/boot/${BOOT_IMAGE_PATH}/${BOOT_IMAGE_NAME}" ]; then
+ BOOT_IMAGE_NAME="vmlinuz-${KERNEL}"
+ BOOT_IMAGE_PATH=""
+ fi
+ fi
+
+ BOOT_IMAGE_HMAC="/boot/${BOOT_IMAGE_PATH}/.${BOOT_IMAGE_NAME}.hmac"
+ if ! [ -e "${BOOT_IMAGE_HMAC}" ]; then
+ warn "${BOOT_IMAGE_HMAC} does not exist"
+ return 1
+ fi
+
+ (cd "${BOOT_IMAGE_HMAC%/*}" && sha512hmac -c "${BOOT_IMAGE_HMAC}") || return 1
+ fi
+ fi
+
+ fips_info "All initrd crypto checks done"
+
+ : > /tmp/fipsdone
+
+ if [ "$FIPS_MOUNTED_BOOT" = 1 ]; then
+ fips_info "Unmounting /boot"
+ umount /boot > /dev/null 2>&1
+ else
+ fips_info "Not unmounting /boot"
+ fi
+
+ return 0
+}
diff --git a/modules.d/01fips/module-setup.sh b/modules.d/01fips/module-setup.sh
new file mode 100755
index 0000000..0e47c84
--- /dev/null
+++ b/modules.d/01fips/module-setup.sh
@@ -0,0 +1,85 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ return 255
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ local _fipsmodules _mod _bootfstype
+ if [[ -f "${srcmods}/modules.fips" ]]; then
+ read -d '' -r _fipsmodules < "${srcmods}/modules.fips"
+ else
+ _fipsmodules=""
+
+ # Hashes:
+ _fipsmodules+="sha1 sha224 sha256 sha384 sha512 "
+ _fipsmodules+="sha3-224 sha3-256 sha3-384 sha3-512 "
+ _fipsmodules+="crc32c crct10dif ghash "
+
+ # Ciphers:
+ _fipsmodules+="cipher_null des3_ede aes cfb dh ecdh "
+
+ # Modes/templates:
+ _fipsmodules+="ecb cbc ctr xts gcm ccm authenc hmac cmac ofb cts "
+
+ # Compression algs:
+ _fipsmodules+="deflate lzo zlib "
+
+ # PRNG algs:
+ _fipsmodules+="ansi_cprng "
+
+ # Misc:
+ _fipsmodules+="aead cryptomgr tcrypt crypto_user "
+ fi
+
+ # shellcheck disable=SC2174
+ mkdir -m 0755 -p "${initdir}/etc/modprobe.d"
+
+ for _mod in $_fipsmodules; do
+ if hostonly='' instmods -c -s "$_mod"; then
+ echo "$_mod" >> "${initdir}/etc/fipsmodules"
+ echo "blacklist $_mod" >> "${initdir}/etc/modprobe.d/fips.conf"
+ fi
+ done
+
+ # with hostonly_default_device fs module for /boot is not installed by default
+ if [[ $hostonly ]] && [[ $hostonly_default_device == "no" ]]; then
+ _bootfstype=$(find_mp_fstype /boot)
+ if [[ -n $_bootfstype ]]; then
+ hostonly='' instmods "$_bootfstype"
+ else
+ dwarning "Can't determine fs type for /boot, FIPS check may fail."
+ fi
+ fi
+}
+
+# called by dracut
+install() {
+ inst_hook pre-pivot 00 "$moddir/fips-boot.sh"
+ inst_hook pre-pivot 01 "$moddir/fips-noboot.sh"
+ inst_hook pre-udev 01 "$moddir/fips-load-crypto.sh"
+ inst_script "$moddir/fips.sh" /sbin/fips.sh
+
+ inst_multiple sha512hmac rmmod insmod mount uname umount grep sed cut find sort
+
+ inst_simple /etc/system-fips
+ [ -c "${initdir}"/dev/random ] || mknod "${initdir}"/dev/random c 1 8 \
+ || {
+ dfatal "Cannot create /dev/random"
+ dfatal "To create an initramfs with fips support, dracut has to run as root"
+ return 1
+ }
+ [ -c "${initdir}"/dev/urandom ] || mknod "${initdir}"/dev/urandom c 1 9 \
+ || {
+ dfatal "Cannot create /dev/urandom"
+ dfatal "To create an initramfs with fips support, dracut has to run as root"
+ return 1
+ }
+}
diff --git a/modules.d/01systemd-ac-power/99-initrd-power-targets.rules b/modules.d/01systemd-ac-power/99-initrd-power-targets.rules
new file mode 100644
index 0000000..1490a22
--- /dev/null
+++ b/modules.d/01systemd-ac-power/99-initrd-power-targets.rules
@@ -0,0 +1,3 @@
+# This file is part of dracut systemd ac power module
+SUBSYSTEM=="power_supply", KERNEL=="AC", ATTR{online}=="0", RUN+="/usr/sbin/systemctl start initrd-on-battery-power.target"
+SUBSYSTEM=="power_supply", KERNEL=="AC", ATTR{online}=="1", RUN+="/usr/sbin/systemctl start initrd-on-ac-power.target"
diff --git a/modules.d/01systemd-ac-power/initrd-on-ac-power.target b/modules.d/01systemd-ac-power/initrd-on-ac-power.target
new file mode 100644
index 0000000..73a9978
--- /dev/null
+++ b/modules.d/01systemd-ac-power/initrd-on-ac-power.target
@@ -0,0 +1,8 @@
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+[Unit]
+Description=Initial RAM Disk On AC Power
+ConditionPathExists=/usr/lib/initrd-release
+DefaultDependencies=no
+StopWhenUnneeded=yes
diff --git a/modules.d/01systemd-ac-power/initrd-on-battery-power.target b/modules.d/01systemd-ac-power/initrd-on-battery-power.target
new file mode 100644
index 0000000..fdd54a5
--- /dev/null
+++ b/modules.d/01systemd-ac-power/initrd-on-battery-power.target
@@ -0,0 +1,8 @@
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+[Unit]
+Description=Initial RAM Disk On Battery Power
+ConditionPathExists=/usr/lib/initrd-release
+DefaultDependencies=no
+StopWhenUnneeded=yes
diff --git a/modules.d/01systemd-ac-power/module-setup.sh b/modules.d/01systemd-ac-power/module-setup.sh
new file mode 100755
index 0000000..c4e7fdd
--- /dev/null
+++ b/modules.d/01systemd-ac-power/module-setup.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+
+ inst_rules "$moddir/99-initrd-power-targets.rules"
+ inst systemd-ac-power
+ inst_simple "$moddir/initrd-on-ac-power.target" "$systemdsystemunitdir/initrd-on-ac-power.target"
+ inst_simple "$moddir/initrd-on-battery-power.target" "$systemdsystemunitdir/initrd-on-battery-power.target"
+
+}
diff --git a/modules.d/01systemd-ask-password/module-setup.sh b/modules.d/01systemd-ask-password/module-setup.sh
new file mode 100755
index 0000000..6e78075
--- /dev/null
+++ b/modules.d/01systemd-ask-password/module-setup.sh
@@ -0,0 +1,60 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed
+ require_binaries \
+ systemd-ask-password \
+ systemd-tty-ask-password-agent \
+ || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install the required file(s) for the module in the initramfs.
+install() {
+
+ inst_multiple -o \
+ "$systemdsystemunitdir"/systemd-ask-password-console.path \
+ "$systemdsystemunitdir"/systemd-ask-password-console.service \
+ "$systemdsystemunitdir"/multi-user.target.wants/systemd-ask-password-wall.path \
+ "$systemdsystemunitdir"/sysinit.target.wants/systemd-ask-password-console.path \
+ systemd-ask-password \
+ systemd-tty-ask-password-agent
+
+ # Enable the systemd type service unit for systemd-ask-password.
+ $SYSTEMCTL -q --root "$initdir" enable systemd-ask-password-console.service
+
+ # Install systemd-ask-password plymouth units if plymouth is enabled.
+ if dracut_module_included "plymouth"; then
+ inst_multiple -o \
+ "$systemdsystemunitdir"/systemd-ask-password-plymouth.path \
+ "$systemdsystemunitdir"/systemd-ask-password-plymouth.service
+
+ $SYSTEMCTL -q --root "$initdir" enable systemd-ask-password-plymouth.service
+ fi
+
+ # Uncomment this section if the usecase for wall module in the initramfs arises.
+ # Install systemd-ask-password wall units if <wall module> is enabled.
+ #if dracut_module_included "<wall module>"; then
+ # inst_multiple -o \
+ # $systemdsystemunitdir/systemd-ask-password-wall.path \
+ # $systemdsystemunitdir/systemd-ask-password-wall.service \
+ # $systemdsystemunitdir/multi-user.target.wants/systemd-ask-password-wall.path \
+ #
+ # $SYSTEMCTL -q --root "$initdir" enable systemd-ask-password-wall.service
+ #fi
+}
diff --git a/modules.d/01systemd-coredump/module-setup.sh b/modules.d/01systemd-coredump/module-setup.sh
new file mode 100755
index 0000000..69ec966
--- /dev/null
+++ b/modules.d/01systemd-coredump/module-setup.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed
+ require_binaries \
+ coredumpctl \
+ "$systemdutildir"/systemd-coredump \
+ || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # This module has external dependency on the systemd module.
+ echo systemd-journald systemd-sysctl systemd-sysusers
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+
+ inst_dir /var/lib/systemd/coredump
+ inst_multiple -o \
+ "$sysctld"/50-coredump.conf \
+ "$systemdutildir"/coredump.conf \
+ "$systemdutildir"/systemd-coredump \
+ "$systemdsystemunitdir"/systemd-coredump.socket \
+ "$systemdsystemunitdir"/systemd-coredump@.service \
+ "$systemdsystemunitdir"/sockets.target.wants/systemd-coredump.socket \
+ "$sysusers"/systemd-coredump.conf \
+ coredumpctl
+
+ # Install the hosts local user configurations if enabled.
+ if [[ $hostonly ]]; then
+ inst_multiple -H -o \
+ "$systemdutilconfdir"/coredump.conf \
+ "$systemdsystemconfdir/coredump.conf.d/*.conf" \
+ "$systemdsystemconfdir"/systemd-coredump.socket \
+ "$systemdsystemconfdir/systemd-coredump.socket.d/*.conf" \
+ "$systemdsystemconfdir"/systemd-coredump@.service \
+ "$systemdsystemconfdir/systemd-coredump@.service.d/*.conf" \
+ "$systemdsystemconfdir"/sockets.target.wants/systemd-coredump.socket \
+ "$sysusersconfdir"/systemd-coredump.conf
+ fi
+}
diff --git a/modules.d/01systemd-creds/module-setup.sh b/modules.d/01systemd-creds/module-setup.sh
new file mode 100755
index 0000000..1b66519
--- /dev/null
+++ b/modules.d/01systemd-creds/module-setup.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed.
+ require_binaries systemd-creds || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+ local deps
+
+ # This module has external dependency on other module(s).
+ deps="systemd"
+ systemd-creds -q has-tpm2 && deps+=" tpm2-tss"
+ echo "$deps"
+
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+
+ inst_multiple -o \
+ "/usr/lib/credstore/*" \
+ "/usr/lib/credstore.encrypted/*" \
+ "$tmpfilesdir/credstore.conf" \
+ systemd-creds
+
+ # Install the hosts local user configurations if enabled.
+ if [[ $hostonly ]]; then
+ inst_multiple -H -o \
+ "/etc/credstore/*" \
+ "/etc/credstore.encrypted/*"
+ fi
+
+}
diff --git a/modules.d/01systemd-hostnamed/99-systemd-networkd-dracut.conf b/modules.d/01systemd-hostnamed/99-systemd-networkd-dracut.conf
new file mode 100644
index 0000000..2e53e2d
--- /dev/null
+++ b/modules.d/01systemd-hostnamed/99-systemd-networkd-dracut.conf
@@ -0,0 +1,6 @@
+# This file is part of dracut systemd-hostnamed module.
+
+[Service]
+User=systemd-network
+Group=systemd-hostname
+AmbientCapabilities=CAP_SYS_ADMIN
diff --git a/modules.d/01systemd-hostnamed/module-setup.sh b/modules.d/01systemd-hostnamed/module-setup.sh
new file mode 100755
index 0000000..2a1fa02
--- /dev/null
+++ b/modules.d/01systemd-hostnamed/module-setup.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed.
+ require_binaries \
+ hostnamectl \
+ "$systemdutildir"/systemd-hostnamed \
+ || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # This module has external dependency on other module(s).
+ echo dbus systemd-sysusers
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+
+ inst_simple "$moddir/systemd-hostname-dracut.conf" "$sysusers/systemd-hostname-dracut.conf"
+ inst_simple "$moddir/org.freedesktop.hostname1_dracut.conf" "$dbussystem/org.freedesktop.hostname1_dracut.conf"
+ inst_simple "$moddir/99-systemd-networkd-dracut.conf" "$systemdsystemunitdir/systemd-hostnamed.service.d/99-systemd-networkd-dracut.conf"
+
+ inst_multiple -o \
+ "$dbussystem"/org.freedesktop.hostname1.conf \
+ "$dbussystemservices"/org.freedesktop.hostname1.service \
+ "$systemdutildir"/systemd-hostnamed \
+ "$systemdsystemunitdir"/systemd-hostnamed.service \
+ "$systemdsystemunitdir/systemd-hostnamed.service.d/*.conf" \
+ "$systemdsystemunitdir"/dbus-org.freedesktop.hostname1.service \
+ hostnamectl
+
+ # Install the hosts local user configurations if enabled.
+ if [[ $hostonly ]]; then
+ inst_multiple -H -o \
+ /etc/hostname \
+ "$systemdsystemconfdir"/systemd-hostnamed.service \
+ "$systemdsystemconfdir/systemd-hostnamed.service.d/*.conf"
+ fi
+}
diff --git a/modules.d/01systemd-hostnamed/org.freedesktop.hostname1_dracut.conf b/modules.d/01systemd-hostnamed/org.freedesktop.hostname1_dracut.conf
new file mode 100644
index 0000000..4410c1c
--- /dev/null
+++ b/modules.d/01systemd-hostnamed/org.freedesktop.hostname1_dracut.conf
@@ -0,0 +1,19 @@
+<?xml version="1.0"?> <!--*-nxml-*-->
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+
+<!--
+
+ This file is part of dracut systemd-hostnamed module.
+
+-->
+
+<busconfig>
+
+ <policy group="systemd-hostname">
+ <allow own="org.freedesktop.hostname1"/>
+ <allow send_destination="org.freedesktop.hostname1"/>
+ <allow receive_sender="org.freedesktop.hostname1"/>
+ </policy>
+
+</busconfig>
diff --git a/modules.d/01systemd-hostnamed/systemd-hostname-dracut.conf b/modules.d/01systemd-hostnamed/systemd-hostname-dracut.conf
new file mode 100644
index 0000000..3acb748
--- /dev/null
+++ b/modules.d/01systemd-hostnamed/systemd-hostname-dracut.conf
@@ -0,0 +1,2 @@
+# This file is part of dracut systemd-hostnamed module.
+g systemd-hostname -
diff --git a/modules.d/01systemd-initrd/module-setup.sh b/modules.d/01systemd-initrd/module-setup.sh
new file mode 100755
index 0000000..f65041f
--- /dev/null
+++ b/modules.d/01systemd-initrd/module-setup.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ [[ $mount_needs ]] && return 1
+
+ return 0
+}
+
+# called by dracut
+depends() {
+ echo "systemd"
+}
+
+installkernel() {
+ return 0
+}
+
+# called by dracut
+install() {
+ inst_multiple -o \
+ "$systemdsystemunitdir"/initrd.target \
+ "$systemdsystemunitdir"/initrd-fs.target \
+ "$systemdsystemunitdir"/initrd-root-device.target \
+ "$systemdsystemunitdir"/initrd-root-fs.target \
+ "$systemdsystemunitdir"/initrd-usr-fs.target \
+ "$systemdsystemunitdir"/initrd-switch-root.target \
+ "$systemdsystemunitdir"/initrd-switch-root.service \
+ "$systemdsystemunitdir"/initrd-cleanup.service \
+ "$systemdsystemunitdir"/initrd-udevadm-cleanup-db.service \
+ "$systemdsystemunitdir"/initrd-parse-etc.service
+
+ $SYSTEMCTL -q --root "$initdir" set-default initrd.target
+}
diff --git a/modules.d/01systemd-integritysetup/module-setup.sh b/modules.d/01systemd-integritysetup/module-setup.sh
new file mode 100755
index 0000000..3d17640
--- /dev/null
+++ b/modules.d/01systemd-integritysetup/module-setup.sh
@@ -0,0 +1,59 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed.
+ require_binaries \
+ "$systemdutildir"/systemd-integritysetup \
+ "$systemdutildir"/system-generators/systemd-integritysetup-generator \
+ || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # This module has external dependency on other module(s).
+ echo systemd dm
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+installkernel() {
+ instmods dm-integrity
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+
+ inst_multiple -o \
+ "$systemdutildir"/systemd-integritysetup \
+ "$systemdutildir"/system-generators/systemd-integritysetup-generator \
+ "$systemdsystemunitdir"/integritysetup-pre.target \
+ "$systemdsystemunitdir"/integritysetup.target \
+ "$systemdsystemunitdir"/sysinit.target.wants/integritysetup.target
+
+ # Install the hosts local user configurations if enabled.
+ if [[ $hostonly ]]; then
+ inst_multiple -H -o \
+ /etc/integritytab \
+ "$systemdsystemconfdir"/integritysetup.target \
+ "$systemdsystemconfdir/integritysetup.target.wants/*.target" \
+ "$systemdsystemconfdir"/integritysetup-pre.target \
+ "$systemdsystemconfdir/integritysetup-pre.target.wants/*.target" \
+ "$systemdsystemconfdir"/sysinit.target.wants/integritysetup.target \
+ "$systemdsystemconfdir/sysinit.target.wants/integritysetup.target.wants/*.target"
+ fi
+
+ # Install required libraries.
+ _arch=${DRACUT_ARCH:-$(uname -m)}
+ inst_libdir_file {"tls/$_arch/",tls/,"$_arch/",}"libcryptsetup.so.*"
+
+}
diff --git a/modules.d/01systemd-journald/initrd.conf b/modules.d/01systemd-journald/initrd.conf
new file mode 100644
index 0000000..1246e05
--- /dev/null
+++ b/modules.d/01systemd-journald/initrd.conf
@@ -0,0 +1,9 @@
+# This file is part of dracut systemd-journal module.
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Dracut requires volatile journal without rate-limiting
+
+[Journal]
+Storage=volatile
+RateLimitInterval=0
+RateLimitBurst=0
diff --git a/modules.d/01systemd-journald/module-setup.sh b/modules.d/01systemd-journald/module-setup.sh
new file mode 100755
index 0000000..3cf2a1a
--- /dev/null
+++ b/modules.d/01systemd-journald/module-setup.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed.
+ require_binaries \
+ journalctl \
+ "$systemdutildir"/systemd-journald \
+ || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # This module has external dependency on other module(s).
+ echo systemd-sysusers
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+
+ inst_simple "$moddir/initrd.conf" "$systemdutildir/journald.conf.d/initrd.conf"
+
+ inst_multiple -o \
+ "$systemdutildir"/journald.conf \
+ "$systemdutildir/journald.conf.d/*.conf" \
+ "$systemdutildir"/systemd-journald \
+ "$systemdsystemunitdir"/systemd-journald.service \
+ "$systemdsystemunitdir"/systemd-journald.socket \
+ "$systemdsystemunitdir"/systemd-journald@.service \
+ "$systemdsystemunitdir"/systemd-journald@.socket \
+ "$systemdsystemunitdir"/systemd-journald-audit.socket \
+ "$systemdsystemunitdir"/systemd-journald-dev-log.socket \
+ "$systemdsystemunitdir"/systemd-journald-varlink@.socket \
+ "$systemdsystemunitdir"/systemd-journal-catalog-update.service \
+ "$systemdsystemunitdir"/sockets.target.wants/systemd-journald-audit.socket \
+ "$systemdsystemunitdir"/sockets.target.wants/systemd-journald-dev-log.socket \
+ "$systemdsystemunitdir"/sockets.target.wants/systemd-journald.socket \
+ "$systemdsystemunitdir"/sysinit.target.wants/systemd-journald.service \
+ "$sysusers"/systemd-journal.conf \
+ journalctl
+
+ # Install library file(s)
+ _arch=${DRACUT_ARCH:-$(uname -m)}
+ inst_libdir_file \
+ {"tls/$_arch/",tls/,"$_arch/",}"liblz4.so.*" \
+ {"tls/$_arch/",tls/,"$_arch/",}"libzstd.so.*" \
+ {"tls/$_arch/",tls/,"$_arch/",}"liblzma.so.*"
+
+ # Install the hosts local user configurations if enabled.
+ if [[ $hostonly ]]; then
+ inst_multiple -H -o \
+ "$systemdutilconfdir"/journald.conf \
+ "$systemdutilconfdir/journald.conf.d/*.conf" \
+ "$systemdsystemconfdir"/systemd-journald.service \
+ "$systemdsystemconfdir/systemd-journald.service.d/*.conf" \
+ "$systemdsystemconfdir"/systemd-journal-catalog-update.service \
+ "$systemdsystemconfdir/systemd-journal-catalog-update.service.d/*.conf" \
+ "$sysusersconfdir"/systemd-journal.conf
+ fi
+
+}
diff --git a/modules.d/01systemd-ldconfig/module-setup.sh b/modules.d/01systemd-ldconfig/module-setup.sh
new file mode 100755
index 0000000..3a5842a
--- /dev/null
+++ b/modules.d/01systemd-ldconfig/module-setup.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed.
+ require_binaries ldconfig || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # This module has external dependency on other module(s).
+ echo systemd
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+
+ inst_multiple -o \
+ /etc/ld.so.cache \
+ /etc/ld.so.conf \
+ "/etc/ld.so.conf.d/*.conf" \
+ "$systemdsystemunitdir"/ldconfig.service \
+ "$systemdsystemunitdir/ldconfig.service.d/*.conf" \
+ "$systemdsystemunitdir"/sysinit.target.wants/ldconfig.service \
+ ldconfig
+
+ # Install required libraries.
+ _arch=${DRACUT_ARCH:-$(uname -m)}
+ inst_libdir_file {"tls/$_arch/",tls/,"$_arch/",}"ld.so"
+
+ # Install the hosts local user configurations if enabled.
+ if [[ $hostonly ]]; then
+ inst_multiple -H -o \
+ "$systemdsystemconfdir"/ldconfig.service \
+ "$systemdsystemconfdir/ldconfig.service.d/*.conf"
+ fi
+
+}
diff --git a/modules.d/01systemd-modules-load/module-setup.sh b/modules.d/01systemd-modules-load/module-setup.sh
new file mode 100755
index 0000000..f9adfea
--- /dev/null
+++ b/modules.d/01systemd-modules-load/module-setup.sh
@@ -0,0 +1,44 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed
+ require_binaries "$systemdutildir"/systemd-modules-load || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+
+ inst_multiple -o \
+ "$modulesload/*.conf" \
+ "$systemdutildir"/systemd-modules-load \
+ "$systemdsystemunitdir"/systemd-modules-load.service \
+ "$systemdsystemunitdir"/sysinit.target.wants/systemd-modules-load.service
+
+ # Enable systemd type unit(s)
+ $SYSTEMCTL -q --root "$initdir" enable systemd-modules-load.service
+
+ # Install the hosts local user configurations if enabled.
+ if [[ $hostonly ]]; then
+ inst_multiple -H -o \
+ "$modulesloadconfdir/*.conf" \
+ "$systemdsystemconfdir"/systemd-modules-load.service \
+ "$systemdsystemconfdir/systemd-modules-load.service.d/*.conf"
+ fi
+
+}
diff --git a/modules.d/01systemd-networkd/module-setup.sh b/modules.d/01systemd-networkd/module-setup.sh
new file mode 100755
index 0000000..7bbf83c
--- /dev/null
+++ b/modules.d/01systemd-networkd/module-setup.sh
@@ -0,0 +1,87 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+ [[ $mount_needs ]] && return 1
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed
+ require_binaries ip networkctl \
+ "$systemdutildir"/systemd-networkd \
+ "$systemdutildir"/systemd-network-generator \
+ "$systemdutildir"/systemd-networkd-wait-online \
+ || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # This module has external dependency on other module(s).
+ echo dbus kernel-network-modules systemd-sysusers
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+
+ inst_multiple -o \
+ "$tmpfilesdir"/systemd-network.conf \
+ "$dbussystem"/org.freedesktop.network1.conf \
+ "$dbussystemservices"/org.freedesktop.network1.service \
+ "$systemdutildir"/networkd.conf \
+ "$systemdutildir/networkd.conf.d/*.conf" \
+ "$systemdutildir"/systemd-networkd \
+ "$systemdutildir"/systemd-network-generator \
+ "$systemdutildir"/systemd-networkd-wait-online \
+ "$systemdnetwork"/80-6rd-tunnel.network \
+ "$systemdnetwork"/80-container-host0.network \
+ "$systemdnetwork"/80-container-vb.network \
+ "$systemdnetwork"/80-container-ve.network \
+ "$systemdnetwork"/80-container-vz.network \
+ "$systemdnetwork"/80-vm-vt.network \
+ "$systemdnetwork"/80-wifi-adhoc.network \
+ "$systemdnetwork"/99-default.link \
+ "$systemdsystemunitdir"/systemd-networkd.service \
+ "$systemdsystemunitdir"/systemd-networkd.socket \
+ "$systemdsystemunitdir"/systemd-network-generator.service \
+ "$systemdsystemunitdir"/systemd-networkd-wait-online.service \
+ "$systemdsystemunitdir"/systemd-networkd-wait-online@.service \
+ "$systemdsystemunitdir"/systemd-network-generator.service \
+ "$sysusers"/systemd-network.conf \
+ networkctl ip
+
+ # Enable systemd type units
+ for i in \
+ systemd-networkd.service \
+ systemd-networkd.socket \
+ systemd-network-generator.service \
+ systemd-networkd-wait-online.service; do
+ $SYSTEMCTL -q --root "$initdir" enable "$i"
+ done
+
+ # Install the hosts local user configurations if enabled.
+ if [[ $hostonly ]]; then
+ inst_multiple -H -o \
+ "$systemdutilconfdir"/networkd.conf \
+ "$systemdutilconfdir/networkd.conf.d/*.conf" \
+ "$systemdnetworkconfdir/*" \
+ "$systemdsystemconfdir"/systemd-networkd.service \
+ "$systemdsystemconfdir/systemd-networkd.service.d/*.conf" \
+ "$systemdsystemconfdir"/systemd-networkd.socket \
+ "$systemdsystemconfdir/systemd-networkd.socket.d/*.conf" \
+ "$systemdsystemconfdir"/systemd-network-generator.service \
+ "$systemdsystemconfdir/systemd-network-generator.service.d/*.conf" \
+ "$systemdsystemconfdir"/systemd-networkd-wait-online.service \
+ "$systemdsystemconfdir/systemd-networkd-wait-online.service.d/*.conf" \
+ "$systemdsystemconfdir"/systemd-networkd-wait-online@.service \
+ "$systemdsystemconfdir/systemd-networkd-wait-online@.service.d/*.conf" \
+ "$sysusersconfdir"/systemd-network.conf
+ fi
+}
diff --git a/modules.d/01systemd-pcrphase/module-setup.sh b/modules.d/01systemd-pcrphase/module-setup.sh
new file mode 100755
index 0000000..fa960a4
--- /dev/null
+++ b/modules.d/01systemd-pcrphase/module-setup.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed.
+ require_binaries "$systemdutildir"/systemd-pcrphase || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # This module has external dependency on other module(s).
+ echo systemd tpm2-tss
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+
+ inst_multiple -o \
+ "$systemdutildir"/systemd-pcrphase \
+ "$systemdsystemunitdir"/systemd-pcrphase-initrd.service \
+ "$systemdsystemunitdir/systemd-pcrphase-initrd.service.d/*.conf" \
+ "$systemdsystemunitdir"/initrd.target.wants/systemd-pcrphase-initrd.service
+
+ # Install the hosts local user configurations if enabled.
+ if [[ $hostonly ]]; then
+ inst_multiple -H -o \
+ "$systemdsystemconfdir"/systemd-pcrphase-initrd.service \
+ "$systemdsystemconfdir/systemd-pcrphase-initrd.service.d/*.conf" \
+ "$systemdsystemconfdir"/initrd.target.wants/systemd-pcrphase-initrd.service
+ fi
+
+}
diff --git a/modules.d/01systemd-portabled/module-setup.sh b/modules.d/01systemd-portabled/module-setup.sh
new file mode 100755
index 0000000..ccbc11f
--- /dev/null
+++ b/modules.d/01systemd-portabled/module-setup.sh
@@ -0,0 +1,82 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed.
+ require_binaries \
+ portablectl \
+ "$systemdutildir"/systemd-portabled \
+ || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # This module has external dependency on other module(s).
+ echo dbus
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install kernel module(s).
+installkernel() {
+ instmods loop squashfs
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+
+ # It's intended to work only with raw binary disk images contained in
+ # regular files, but not with directory trees.
+ local _nonraw
+ _nonraw=$(portablectl --no-pager --no-legend list | grep -v " raw " | cut -d ' ' -f1 | tr '\n' ' ')
+ if [ -n "$_nonraw" ]; then
+ dwarn "systemd-portabled: this module only installs raw disk images in the initramfs; skipping: $_nonraw"
+ fi
+
+ inst_multiple -o \
+ "/var/lib/portables/*.raw" \
+ "/usr/lib/portables/*.raw" \
+ "$tmpfilesdir/portables.conf" \
+ "$dbussystem"/org.freedesktop.portable1.conf \
+ "$dbussystemservices"/org.freedesktop.portable1.service \
+ "$systemdutildir"/systemd-portabled \
+ "$systemdutildir/portable/profile/default/*.conf" \
+ "$systemdutildir/portable/profile/nonetwork/*.conf" \
+ "$systemdutildir/portable/profile/strict/*.conf" \
+ "$systemdutildir/portable/profile/trusted/*.conf" \
+ "$systemdsystemunitdir"/systemd-portabled.service \
+ "$systemdsystemunitdir/systemd-portabled.service.d/*.conf" \
+ "$systemdsystemunitdir"/dbus-org.freedesktop.portable1.service \
+ portablectl
+
+ # The existence of this file is required
+ touch "$initdir"/etc/resolv.conf
+
+ # Enable systemd type unit(s)
+ $SYSTEMCTL -q --root "$initdir" add-wants initrd.target systemd-portabled.service
+ $SYSTEMCTL -q --root "$initdir" enable systemd-portabled.service
+
+ # Install the hosts local user configurations if enabled.
+ if [[ $hostonly ]]; then
+ inst_multiple -H -o \
+ "/etc/portables/*.raw" \
+ "$systemdutilconfdir/system.attached/*" \
+ "$systemdutilconfdir/system.attached/*/*" \
+ "$systemdutilconfdir/portable/profile/default/*.conf" \
+ "$systemdutilconfdir/portable/profile/nonetwork/*.conf" \
+ "$systemdutilconfdir/portable/profile/strict/*.conf" \
+ "$systemdutilconfdir/portable/profile/trusted/*.conf" \
+ "$systemdsystemconfdir"/systemd-portabled.service \
+ "$systemdsystemconfdir/systemd-portabled.service.d/*.conf"
+ fi
+
+}
diff --git a/modules.d/01systemd-pstore/module-setup.sh b/modules.d/01systemd-pstore/module-setup.sh
new file mode 100755
index 0000000..67034bb
--- /dev/null
+++ b/modules.d/01systemd-pstore/module-setup.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed.
+ require_binaries "$systemdutildir"/systemd-pstore || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # This module has external dependency on other module(s).
+ echo systemd
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install kernel module(s).
+installkernel() {
+ instmods efi-pstore
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+
+ inst_dir /var/lib/systemd/pstore
+ inst_multiple -o \
+ "$tmpfilesdir/systemd-pstore.conf" \
+ "$systemdutildir"/systemd-pstore \
+ "$systemdsystemunitdir"/systemd-pstore.service \
+ "$systemdsystemunitdir/systemd-pstore.service.d/*.conf"
+
+ # Enable systemd type unit(s)
+ $SYSTEMCTL -q --root "$initdir" enable systemd-pstore.service
+
+ # Install the hosts local user configurations if enabled.
+ if [[ $hostonly ]]; then
+ inst_multiple -H -o \
+ "$systemdutilconfdir"/pstore.conf \
+ "$systemdutilconfdir/pstore.conf.d/*.conf" \
+ "$systemdsystemconfdir"/systemd-pstore.service \
+ "$systemdsystemconfdir/systemd-pstore.service.d/*.conf"
+ fi
+
+}
diff --git a/modules.d/01systemd-repart/module-setup.sh b/modules.d/01systemd-repart/module-setup.sh
new file mode 100755
index 0000000..19b7e73
--- /dev/null
+++ b/modules.d/01systemd-repart/module-setup.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed.
+ require_binaries systemd-repart || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install the required file(s) for the module in the initramfs.
+install() {
+
+ inst_multiple -o \
+ "/usr/lib/repart.d/*.conf" \
+ "$systemdsystemunitdir"/systemd-repart.service \
+ "$systemdsystemunitdir"/initrd-root-fs.target.wants/systemd-repart.service \
+ systemd-repart
+
+ # Install the hosts local user configurations if enabled.
+ if [[ $hostonly ]]; then
+ inst_multiple -H -o \
+ "/etc/repart.d/*.conf" \
+ "$systemdsystemconfdir"/systemd-repart.service \
+ "$systemdsystemconfdir/systemd-repart.service.d/*.conf"
+ fi
+}
diff --git a/modules.d/01systemd-resolved/module-setup.sh b/modules.d/01systemd-resolved/module-setup.sh
new file mode 100755
index 0000000..0c2e8c2
--- /dev/null
+++ b/modules.d/01systemd-resolved/module-setup.sh
@@ -0,0 +1,58 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed
+ require_binaries \
+ resolvectl \
+ "$systemdutildir"/systemd-resolved \
+ || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # This module has external dependency on other module(s).
+ echo dbus systemd-sysusers
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+
+ inst_simple "$moddir/resolved-tmpfile-dracut.conf" "$tmpfilesdir/resolved-tmpfile-dracut.conf"
+
+ inst_multiple -o \
+ "$dbussystem"/org.freedesktop.resolve1.conf \
+ "$dbussystemservices"/org.freedesktop.resolve1.service \
+ "$systemdutildir"/resolv.conf \
+ "$systemdutildir"/resolved.conf \
+ "$systemdutildir/resolved.conf.d/*.conf" \
+ "$systemdutildir"/systemd-resolved \
+ "$systemdsystemunitdir"/systemd-resolved.service \
+ "$systemdsystemunitdir/systemd-resolved.service.d/*.conf" \
+ "$sysusers"/systemd-resolve.conf \
+ resolvectl
+
+ # Enable systemd type unit(s)
+ $SYSTEMCTL -q --root "$initdir" enable systemd-resolved.service
+
+ # Install the hosts local user configurations if enabled.
+ if [[ $hostonly ]]; then
+ inst_multiple -H -o \
+ "$systemdutilconfdir"/resolved.conf \
+ "$systemdutilconfdir/resolved.conf.d/*.conf" \
+ "$systemdsystemconfdir"/systemd-resolved.service \
+ "$systemdsystemconfdir/systemd-resolved.service.d/*.conf" \
+ "$sysusersconfdir"/systemd-resolve.conf
+ fi
+}
diff --git a/modules.d/01systemd-resolved/resolved-tmpfile-dracut.conf b/modules.d/01systemd-resolved/resolved-tmpfile-dracut.conf
new file mode 100644
index 0000000..6b7daa9
--- /dev/null
+++ b/modules.d/01systemd-resolved/resolved-tmpfile-dracut.conf
@@ -0,0 +1,2 @@
+# This file is part of dracut systemd-resolved module.
+L! /etc/resolv.conf - - - - ../run/systemd/resolve/stub-resolv.conf
diff --git a/modules.d/01systemd-sysctl/module-setup.sh b/modules.d/01systemd-sysctl/module-setup.sh
new file mode 100755
index 0000000..d0eb779
--- /dev/null
+++ b/modules.d/01systemd-sysctl/module-setup.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed
+ require_binaries "$systemdutildir"/systemd-sysctl || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # This module has external dependency on other module(s).
+ echo systemd-modules-load
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install the required file(s) for the module in the initramfs.
+install() {
+
+ inst_multiple -o \
+ "$sysctld/*.conf" \
+ "$systemdsystemunitdir"/systemd-sysctl.service \
+ "$systemdsystemunitdir"/sysinit.target.wants/systemd-sysctl.service \
+ "$systemdutildir"/systemd-sysctl
+
+ # Install the hosts local user configurations if enabled.
+ if [[ $hostonly ]]; then
+ inst_multiple -H -o \
+ /etc/sysctl.conf \
+ "$sysctlconfdir/*.conf" \
+ "$systemdsystemconfdir"/systemd-sysctl.service \
+ "$systemdsystemconfdir/systemd-sysctl.service.d/*.conf"
+ fi
+
+ # Enable the systemd type service unit for sysctl.
+ $SYSTEMCTL -q --root "$initdir" enable systemd-sysctl.service
+
+}
diff --git a/modules.d/01systemd-sysext/module-setup.sh b/modules.d/01systemd-sysext/module-setup.sh
new file mode 100755
index 0000000..b95a480
--- /dev/null
+++ b/modules.d/01systemd-sysext/module-setup.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed.
+ require_binaries systemd-sysext || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # This module has external dependency on other module(s).
+ echo systemd
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+
+ inst_multiple -o \
+ "/usr/lib/extensions/*" \
+ "/usr/lib/extension-release.d/extension-release.*" \
+ "$systemdsystemunitdir"/systemd-sysext.service \
+ "$systemdsystemunitdir/systemd-sysext.service.d/*.conf" \
+ systemd-sysext
+
+ # Enable systemd type unit(s)
+ $SYSTEMCTL -q --root "$initdir" enable systemd-sysext.service
+
+ # Install the hosts local user configurations if enabled.
+ if [[ $hostonly ]]; then
+ inst_multiple -H -o \
+ "/etc/extensions/*" \
+ "$systemdsystemconfdir"/systemd-sysext.service \
+ "$systemdsystemconfdir/systemd-sysext.service.d/*.conf"
+ fi
+
+}
diff --git a/modules.d/01systemd-sysusers/module-setup.sh b/modules.d/01systemd-sysusers/module-setup.sh
new file mode 100755
index 0000000..4ec48dc
--- /dev/null
+++ b/modules.d/01systemd-sysusers/module-setup.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed.
+ require_binaries systemd-sysusers || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+
+ inst_simple "$moddir/sysusers-dracut.conf" "$systemdsystemunitdir/systemd-sysusers.service.d/sysusers-dracut.conf"
+
+ inst_multiple -o \
+ "$sysusers"/basic.conf \
+ "$sysusers"/systemd.conf \
+ "$systemdsystemunitdir"/systemd-sysusers.service \
+ "$systemdsystemunitdir"/sysinit.target.wants/systemd-sysusers.service \
+ systemd-sysusers
+
+ # Install the hosts local user configurations if enabled.
+ if [[ $hostonly ]]; then
+ inst_multiple -H -o \
+ "$sysusersconfdir"/basic.conf \
+ "$sysusersconfdir"/systemd.conf \
+ "$systemdsystemconfdir"/systemd-sysusers.service \
+ "$systemdsystemconfdir/systemd-sysusers.service.d/*.conf"
+ fi
+
+}
diff --git a/modules.d/01systemd-sysusers/sysusers-dracut.conf b/modules.d/01systemd-sysusers/sysusers-dracut.conf
new file mode 100644
index 0000000..9b13364
--- /dev/null
+++ b/modules.d/01systemd-sysusers/sysusers-dracut.conf
@@ -0,0 +1,2 @@
+[Unit]
+ConditionNeedsUpdate=
diff --git a/modules.d/01systemd-timedated/module-setup.sh b/modules.d/01systemd-timedated/module-setup.sh
new file mode 100755
index 0000000..5e9c5ca
--- /dev/null
+++ b/modules.d/01systemd-timedated/module-setup.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed
+ require_binaries \
+ timedatectl \
+ "$systemdutildir"/systemd-timedated \
+ || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # This module has external dependency on other module(s).
+ echo dbus
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+
+ inst_multiple -o \
+ "$dbussystem"/org.freedesktop.timedate1.conf \
+ "$dbussystemservices"/org.freedesktop.timedate1.service \
+ "$systemdutildir"/systemd-timedated \
+ "$systemdsystemunitdir"/systemd-timedated.service \
+ "$systemdsystemunitdir"/dbus-org.freedesktop.timedate1.service \
+ timedatectl
+
+ # Install the hosts local user configurations if enabled.
+ if [[ $hostonly ]]; then
+ inst_multiple -H -o \
+ "$systemdsystemconfdir"/systemd-timedated.service \
+ "$systemdsystemconfdir/systemd-timedated.service.d/*.conf"
+ fi
+}
diff --git a/modules.d/01systemd-timesyncd/module-setup.sh b/modules.d/01systemd-timesyncd/module-setup.sh
new file mode 100755
index 0000000..a2c6754
--- /dev/null
+++ b/modules.d/01systemd-timesyncd/module-setup.sh
@@ -0,0 +1,67 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed
+ require_binaries \
+ "$systemdutildir"/systemd-timesyncd \
+ "$systemdutildir"/systemd-time-wait-sync \
+ || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # This module has external dependency on other module(s).
+ echo dbus systemd-sysusers systemd-timedated
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+
+ # Enable this if networkd ( not the module ) is disabled at build time and you want to use timesyncd
+ # inst_simple "$moddir/timesyncd-tmpfile-dracut.conf" "$tmpfilesdir/timesyncd-tmpfile-dracut.conf"
+
+ inst_multiple -o \
+ "$dbussystem"/org.freedesktop.timesync1.conf \
+ "$dbussystemservices"/org.freedesktop.timesync1.service \
+ "$systemdntpunits/*.list" \
+ "$systemdutildir"/systemd-timesyncd \
+ "$systemdutildir"/systemd-time-wait-sync \
+ "$systemdutildir/timesyncd.conf.d/*.conf" \
+ "$systemdsystemunitdir"/systemd-timesyncd.service \
+ "$systemdsystemunitdir/systemd-timesyncd.service.d/*.conf" \
+ "$systemdsystemunitdir"/systemd-time-wait-sync.service \
+ "$systemdsystemunitdir/systemd-time-wait-sync.service.d/*.conf" \
+ "$sysusers"/systemd-timesync.conf
+
+ # Enable systemd type unit(s)
+ for i in \
+ systemd-timesyncd.service \
+ systemd-time-wait-sync.service; do
+ $SYSTEMCTL -q --root "$initdir" enable "$i"
+ done
+
+ # Install the hosts local user configurations if enabled.
+ if [[ $hostonly ]]; then
+ inst_multiple -H -o \
+ "$systemdntpunitsconfdir/*.list" \
+ "$systemdutilconfdir"/timesyncd.conf \
+ "$systemdutilconfdir/timesyncd.conf.d/*.conf" \
+ "$systemdsystemconfdir"/systemd-timesyncd.service \
+ "$systemdsystemconfdir/systemd-timesyncd.service.d/*.conf" \
+ "$systemdsystemconfdir"/systemd-time-wait-sync.service \
+ "$systemdsystemconfdir/systemd-time-wait-sync.service.d/*.conf" \
+ "$sysusersconfdir"/systemd-timesync.conf
+ fi
+}
diff --git a/modules.d/01systemd-timesyncd/timesyncd-tmpfile-dracut.conf b/modules.d/01systemd-timesyncd/timesyncd-tmpfile-dracut.conf
new file mode 100644
index 0000000..14c78bb
--- /dev/null
+++ b/modules.d/01systemd-timesyncd/timesyncd-tmpfile-dracut.conf
@@ -0,0 +1,2 @@
+# This file is part of dracut systemd-timesyncd module.
+d /run/systemd/netif/links 0755 root root -
diff --git a/modules.d/01systemd-tmpfiles/module-setup.sh b/modules.d/01systemd-tmpfiles/module-setup.sh
new file mode 100755
index 0000000..6bd42c0
--- /dev/null
+++ b/modules.d/01systemd-tmpfiles/module-setup.sh
@@ -0,0 +1,71 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed.
+ require_binaries systemd-tmpfiles || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+
+ # Excluding "$tmpfilesdir/home.conf", sets up /home /srv
+ # Excluding "$tmpfilesdir/journal-nocow.conf", requires specific btrfs setup
+ # Excluding "$tmpfilesdir/legacy.conf", belongs in separated legacy module
+ # Excluding "$tmpfilesdir/systemd-nologin.conf", belongs in separated pam module
+ # Excluding "$tmpfilesdir/systemd-nspawn.conf", belongs in separated machined module
+ # Excluding "$tmpfilesdir/x11.conf", belongs in separated x11 module
+
+ inst_multiple -o \
+ /usr/lib/group \
+ /usr/lib/passwd \
+ "$tmpfilesdir/etc.conf" \
+ "$tmpfilesdir/static-nodes-permissions.conf" \
+ "$tmpfilesdir/systemd-tmp.conf" \
+ "$tmpfilesdir/systemd.conf" \
+ "$tmpfilesdir/var.conf" \
+ "$systemdsystemunitdir"/systemd-tmpfiles-clean.service \
+ "$systemdsystemunitdir/systemd-tmpfiles-clean.service.d/*.conf" \
+ "$systemdsystemunitdir"/systemd-tmpfiles-setup.service \
+ "$systemdsystemunitdir/systemd-tmpfiles-setup.service.d/*.conf" \
+ "$systemdsystemunitdir"/systemd-tmpfiles-setup-dev.service \
+ "$systemdsystemunitdir/systemd-tmpfiles-setup-dev.service.d/*.conf" \
+ "$systemdsystemunitdir"/systemd-tmpfiles-setup-dev-early.service \
+ "$systemdsystemunitdir/systemd-tmpfiles-setup-dev-early.service.d/*.conf" \
+ "$systemdsystemunitdir"/sysinit.target.wants/systemd-tmpfiles-setup.service \
+ "$systemdsystemunitdir"/sysinit.target.wants/systemd-tmpfiles-setup-dev.service \
+ "$systemdsystemunitdir"/sysinit.target.wants/systemd-tmpfiles-setup-dev-early.service \
+ systemd-tmpfiles
+
+ # Install the hosts local user configurations if enabled.
+ if [[ $hostonly ]]; then
+ inst_multiple -H -o \
+ /etc/group \
+ /etc/passwd \
+ "$tmpfilesconfdir/*.conf" \
+ "$systemdsystemconfdir"/systemd-tmpfiles-clean.service \
+ "$systemdsystemconfdir/systemd-tmpfiles-clean.service.d/*.conf" \
+ "$systemdsystemconfdir"/systemd-tmpfiles-setup.service \
+ "$systemdsystemconfdir/systemd-tmpfiles-setup.service.d/*.conf" \
+ "$systemdsystemconfdir"/systemd-tmpfiles-setup-dev.service \
+ "$systemdsystemconfdir/systemd-tmpfiles-setup-dev.service.d/*.conf" \
+ "$systemdsystemconfdir"/systemd-tmpfiles-setup-dev-early.service \
+ "$systemdsystemconfdir/systemd-tmpfiles-setup-dev-early.service.d/*.conf"
+ fi
+
+}
diff --git a/modules.d/01systemd-udevd/module-setup.sh b/modules.d/01systemd-udevd/module-setup.sh
new file mode 100755
index 0000000..ce5d2a3
--- /dev/null
+++ b/modules.d/01systemd-udevd/module-setup.sh
@@ -0,0 +1,112 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed.
+ require_binaries \
+ udevadm \
+ "$systemdutildir"/systemd-udevd \
+ || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # This module has external dependency on other module(s).
+ echo systemd
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+
+ inst_multiple -o \
+ "$udevdir"/hwdb.bin \
+ "$udevdir"/udev.conf \
+ "$udevdir"/ata_id \
+ "$udevdir"/cdrom_id \
+ "$udevdir"/dmi_memory_id \
+ "$udevdir"/fido_id \
+ "$udevdir"/mtd_probe \
+ "$udevdir"/mtp-probe \
+ "$udevdir"/scsi_id \
+ "$udevdir"/v4l_id \
+ "$udevrulesdir"/50-udev-default.rules \
+ "$udevrulesdir"/60-autosuspend.rules \
+ "$udevrulesdir"/60-block.rules \
+ "$udevrulesdir"/60-cdrom_id.rules \
+ "$udevrulesdir"/60-drm.rules \
+ "$udevrulesdir"/60-evdev.rules \
+ "$udevrulesdir"/60-fido-id.rules \
+ "$udevrulesdir"/60-input-id.rules \
+ "$udevrulesdir"/60-persistent-alsa.rules \
+ "$udevrulesdir"/60-persistent-input.rules \
+ "$udevrulesdir"/60-persistent-storage-tape.rules \
+ "$udevrulesdir"/60-persistent-storage.rules \
+ "$udevrulesdir"/60-persistent-v4l.rules \
+ "$udevrulesdir"/60-sensor.rules \
+ "$udevrulesdir"/60-serial.rules \
+ "$udevrulesdir"/64-btrfs.rules \
+ "$udevrulesdir"/70-joystick.rules \
+ "$udevrulesdir"/70-memory.rules \
+ "$udevrulesdir"/70-mouse.rules \
+ "$udevrulesdir"/70-touchpad.rules \
+ "$udevrulesdir"/75-net-description.rules \
+ "$udevrulesdir"/75-probe_mtd.rules \
+ "$udevrulesdir"/78-sound-card.rules \
+ "$udevrulesdir"/80-drivers.rules \
+ "$udevrulesdir"/80-net-setup-link.rules \
+ "$udevrulesdir"/81-net-dhcp.rules \
+ "$udevrulesdir"/99-systemd.rules \
+ "$systemdutildir"/systemd-udevd \
+ "$systemdsystemunitdir"/systemd-udevd.service \
+ "$systemdsystemunitdir/systemd-udevd.service.d/*.conf" \
+ "$systemdsystemunitdir"/systemd-udev-trigger.service \
+ "$systemdsystemunitdir/systemd-udev-trigger.service.d/*.conf" \
+ "$systemdsystemunitdir"/systemd-udev-settle.service \
+ "$systemdsystemunitdir/systemd-udev-settle.service.d/*.conf" \
+ "$systemdsystemunitdir"/systemd-udevd-control.socket \
+ "$systemdsystemunitdir"/systemd-udevd-kernel.socket \
+ "$systemdsystemunitdir"/sockets.target.wants/systemd-udevd-control.socket \
+ "$systemdsystemunitdir"/sockets.target.wants/systemd-udevd-kernel.socket \
+ "$systemdsystemunitdir"/sysinit.target.wants/systemd-udevd.service \
+ "$systemdsystemunitdir"/sysinit.target.wants/systemd-udev-trigger.service \
+ udevadm
+
+ # Install the hosts local user configurations if enabled.
+ if [[ $hostonly ]]; then
+ inst_multiple -H -o \
+ "$udevconfdir"/hwdb.bin \
+ "$udevconfdir"/udev.conf \
+ "$udevrulesconfdir/*.rules" \
+ "$systemdutilconfdir"/hwdb/hwdb.bin \
+ "$systemdsystemconfdir"/systemd-udevd.service \
+ "$systemdsystemconfdir/systemd-udevd.service.d/*.conf" \
+ "$systemdsystemconfdir"/systemd-udev-trigger.service \
+ "$systemdsystemconfdir/systemd-udev-trigger.service.d/*.conf" \
+ "$systemdsystemconfdir"/systemd-udev-settle.service \
+ "$systemdsystemconfdir/systemd-udev-settle.service.d/*.conf" \
+ "$systemdsystemconfdir"/systemd-udevd-control.socket \
+ "$systemdsystemconfdir/systemd-udevd-control.socket.d/*.conf" \
+ "$systemdsystemconfdir"/systemd-udevd-kernel.socket \
+ "$systemdsystemconfdir/systemd-udevd-kernel.socket.d/*.conf" \
+ "$systemdsystemconfdir"/sockets.target.wants/systemd-udevd-control.socket \
+ "$systemdsystemconfdir"/sockets.target.wants/systemd-udevd-kernel.socket \
+ "$systemdsystemconfdir"/sysinit.target.wants/systemd-udevd.service \
+ "$systemdsystemconfdir"/sysinit.target.wants/systemd-udev-trigger.service
+ fi
+
+ # Install required libraries.
+ _arch=${DRACUT_ARCH:-$(uname -m)}
+ inst_libdir_file {"tls/$_arch/",tls/,"$_arch/",}"libudev.so.*"
+
+}
diff --git a/modules.d/01systemd-veritysetup/module-setup.sh b/modules.d/01systemd-veritysetup/module-setup.sh
new file mode 100755
index 0000000..fecfecc
--- /dev/null
+++ b/modules.d/01systemd-veritysetup/module-setup.sh
@@ -0,0 +1,60 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed.
+ require_binaries \
+ "$systemdutildir"/systemd-veritysetup \
+ "$systemdutildir"/system-generators/systemd-veritysetup-generator \
+ || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # This module has external dependency on other module(s).
+ echo systemd dm
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+
+ inst_multiple -o \
+ "$systemdutildir"/systemd-veritysetup \
+ "$systemdutildir"/system-generators/systemd-veritysetup-generator \
+ "$systemdsystemunitdir"/remote-veritysetup.target \
+ "$systemdsystemunitdir"/veritysetup-pre.target \
+ "$systemdsystemunitdir"/veritysetup.target \
+ "$systemdsystemunitdir"/sysinit.target.wants/veritysetup.target \
+ "$systemdsystemunitdir"/initrd-root-device.target.wants/remote-veritysetup.target
+
+ # Install the hosts local user configurations if enabled.
+ if [[ $hostonly ]]; then
+ inst_multiple -H -o \
+ /etc/veritytab \
+ "$systemdsystemconfdir"/veritysetup.target \
+ "$systemdsystemconfdir/veritysetup.target.wants/*.target" \
+ "$systemdsystemconfdir"/veritysetup-pre.target \
+ "$systemdsystemconfdir/veritysetup-pre.target.wants/*.target" \
+ "$systemdsystemconfdir"/remote-veritysetup.target \
+ "$systemdsystemconfdir/remote-veritysetup.target.wants/*.target" \
+ "$systemdsystemconfdir"/sysinit.target.wants/veritysetup.target \
+ "$systemdsystemconfdir/sysinit.target.wants/veritysetup.target.wants/*.target" \
+ "$systemdsystemconfdir"/initrd-root-device.target.wants/remote-veritysetup.target
+ fi
+
+ # Install required libraries.
+ _arch=${DRACUT_ARCH:-$(uname -m)}
+ inst_libdir_file {"tls/$_arch/",tls/,"$_arch/",}"libcryptsetup.so.*"
+
+}
diff --git a/modules.d/02caps/README b/modules.d/02caps/README
new file mode 100644
index 0000000..34e0f02
--- /dev/null
+++ b/modules.d/02caps/README
@@ -0,0 +1,33 @@
+This adds the following parameters:
+rd.caps=1
+ turn the caps module on/off
+rd.caps.initdrop=cap_sys_module,cap_sys_rawio
+ drop the specified comma separated capabilities
+rd.caps.disablemodules=1
+ turn off module loading
+rd.caps.disablekexec=1
+ turn off the kexec functionality
+
+If module loading is turned off, all modules have to be loaded in the
+initramfs, which are used later on. This can be done with
+"rd.driver.pre="
+rd.driver.pre=autofs4,sunrpc,ipt_REJECT,nf_conntrack_ipv4,....
+
+Because the kernel command line would get huge with all those drivers, I
+recommend to make use of $initramfs/etc/cmdline.
+
+So, all rd.caps.* and rd.driver.pre arguments are in caps.conf can be
+copied to $initramfs/etc/cmdline with "-i caps.conf /etc/cmdline".
+
+Also all modules have to be loaded in the initramfs via "--add-drivers".
+
+The resulting initramfs creation would look like this:
+
+ --add-drivers "autofs4 sunrpc ipt_REJECT nf_conntrack_ipv4 \
+ nf_defrag_ipv4 iptable_filter ip_tables
+ ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 xt_state nf_conntrack
+ ip6table_filter ip6_tables dm_mirror dm_region_hash dm_log uinput ppdev
+ parport_pc parport ipv6 sg 8139too 8139cp mii i2c_piix4 i2c_core ext3
+ jbd mbcache sd_mod crc_t10dif sr_mod cdrom ata_generic pata_acpi ata_piix
+ dm_mod" \
+ /boot/initramfs-caps.img
diff --git a/modules.d/02caps/caps.sh b/modules.d/02caps/caps.sh
new file mode 100755
index 0000000..6c28299
--- /dev/null
+++ b/modules.d/02caps/caps.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+capsmode=$(getarg rd.caps)
+
+if [ "$capsmode" = "1" ]; then
+ CAPS_INIT_DROP=$(getarg rd.caps.initdrop=)
+ # shellcheck disable=SC2016
+ CAPS_USERMODEHELPER_BSET=$(capsh --drop="$CAPS_INIT_DROP" -- -c 'while read a b || [ -n "$a" ]; do [ "$a" = "CapBnd:" ] && echo $((0x${b:$((${#b}-8)):8})) $((0x${b:$((${#b}-16)):8})) && break; done < /proc/self/status')
+ CAPS_MODULES_DISABLED=$(getarg rd.caps.disablemodules=)
+ CAPS_KEXEC_DISABLED=$(getarg rd.caps.disablekexec=)
+
+ info "Loading CAPS_MODULES $CAPS_MODULES"
+ for i in $CAPS_MODULES; do modprobe "$i" 2>&1 > /dev/null | vinfo; done
+
+ if [ "$CAPS_MODULES_DISABLED" = "1" -a -e /proc/sys/kernel/modules_disabled ]; then
+ info "Disabling module loading."
+ echo "$CAPS_MODULES_DISABLED" > /proc/sys/kernel/modules_disabled
+ fi
+
+ if [ "$CAPS_KEXEC_DISABLED" = "1" -a -e /proc/sys/kernel/kexec_disabled ]; then
+ info "Disabling kexec."
+ echo "$CAPS_KEXEC_DISABLED" > /proc/sys/kernel/kexec_disabled
+ fi
+
+ info "CAPS_USERMODEHELPER_BSET=$CAPS_USERMODEHELPER_BSET"
+ if [ -e /proc/sys/kernel/usermodehelper/bset ]; then
+ info "Setting usermode helper bounding set."
+ echo "$CAPS_USERMODEHELPER_BSET" > /proc/sys/kernel/usermodehelper/bset
+ echo "$CAPS_USERMODEHELPER_BSET" > /proc/sys/kernel/usermodehelper/inheritable
+ fi
+
+ echo "CAPS_INIT_DROP=\"$CAPS_INIT_DROP\"" > /etc/capsdrop
+ info "Will drop capabilities $CAPS_INIT_DROP from init."
+fi
diff --git a/modules.d/02caps/module-setup.sh b/modules.d/02caps/module-setup.sh
new file mode 100755
index 0000000..18073e2
--- /dev/null
+++ b/modules.d/02caps/module-setup.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ require_binaries capsh
+ return 255
+}
+
+# called by dracut
+depends() {
+ echo bash
+ return 0
+}
+
+# called by dracut
+install() {
+ if ! dracut_module_included "systemd"; then
+ inst_hook pre-pivot 00 "$moddir/caps.sh"
+ inst "$(find_binary capsh 2> /dev/null)" /usr/sbin/capsh
+ # capsh wants bash and we need bash also
+ inst /bin/bash
+ else
+ dwarning "caps: does not work with systemd in the initramfs"
+ fi
+}
diff --git a/modules.d/03modsign/load-modsign-keys.sh b/modules.d/03modsign/load-modsign-keys.sh
new file mode 100755
index 0000000..a489067
--- /dev/null
+++ b/modules.d/03modsign/load-modsign-keys.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+#
+# Licensed under the GPLv2
+#
+# Copyright 2013 Red Hat, Inc.
+# Peter Jones <pjones@redhat.com>
+
+for x in /lib/modules/keys/*; do
+ [ "${x}" = "/lib/modules/keys/*" ] && break
+ keyctl padd asymmetric "" %:.secondary_trusted_keys < "${x}"
+done
diff --git a/modules.d/03modsign/module-setup.sh b/modules.d/03modsign/module-setup.sh
new file mode 100755
index 0000000..56e2bdb
--- /dev/null
+++ b/modules.d/03modsign/module-setup.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+#
+# Licensed under the GPLv2
+#
+# Copyright 2013 Red Hat, Inc.
+# Peter Jones <pjones@redhat.com>
+
+# called by dracut
+check() {
+ require_binaries keyctl || return 1
+
+ # do not include module in hostonly mode,
+ # if no keys are present
+ if [[ $hostonly ]]; then
+ x=$(echo "$dracutsysrootdir"/lib/modules/keys/*)
+ [[ ${x} == "$dracutsysrootdir/lib/modules/keys/*" ]] && return 255
+ fi
+
+ return 0
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+# called by dracut
+install() {
+ inst_dir /lib/modules/keys
+ inst_binary keyctl
+
+ inst_hook pre-trigger 01 "$moddir/load-modsign-keys.sh"
+
+ for x in "$dracutsysrootdir"/lib/modules/keys/*; do
+ [[ ${x} == "$dracutsysrootdir/lib/modules/keys/*" ]] && break
+ inst_simple "${x#"$dracutsysrootdir"}"
+ done
+}
diff --git a/modules.d/03rescue/module-setup.sh b/modules.d/03rescue/module-setup.sh
new file mode 100755
index 0000000..d7e7e6f
--- /dev/null
+++ b/modules.d/03rescue/module-setup.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ # do not add this module by default
+ return 255
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+# called by dracut
+install() {
+ inst_multiple -o ps grep more cat rm strace free showmount \
+ ping netstat rpcinfo vi scp ping6 ssh \
+ fsck fsck.ext2 fsck.ext4 fsck.ext3 fsck.ext4dev fsck.f2fs fsck.vfat e2fsck
+}
diff --git a/modules.d/04watchdog-modules/module-setup.sh b/modules.d/04watchdog-modules/module-setup.sh
new file mode 100755
index 0000000..2a94e34
--- /dev/null
+++ b/modules.d/04watchdog-modules/module-setup.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ return 255
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+# called by dracut
+install() {
+ return 0
+}
+
+installkernel() {
+ local -A _drivers
+ local _wdtdrv
+
+ for _wd in /sys/class/watchdog/*; do
+ ! [ -e "$_wd" ] && continue
+ _wdtdrv=$(get_dev_module "$_wd")
+ if [[ $_wdtdrv ]]; then
+ instmods "$_wdtdrv"
+ for i in $_wdtdrv; do
+ _drivers[$i]=1
+ done
+ fi
+ done
+
+ # ensure that watchdog module is loaded as early as possible
+ if [[ ${!_drivers[*]} ]]; then
+ echo "rd.driver.pre=\"$(
+ IFS=,
+ echo "${!_drivers[*]}"
+ )\"" > "${initdir}"/etc/cmdline.d/00-watchdog.conf
+ fi
+ return 0
+}
diff --git a/modules.d/04watchdog/module-setup.sh b/modules.d/04watchdog/module-setup.sh
new file mode 100755
index 0000000..e9ce878
--- /dev/null
+++ b/modules.d/04watchdog/module-setup.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ return 255
+}
+
+# called by dracut
+depends() {
+ echo watchdog-modules
+ return 0
+}
+
+# called by dracut
+install() {
+ # Do not add watchdog hooks if systemd module is included
+ # In that case, systemd will manage watchdog kick
+ if ! dracut_module_included "systemd"; then
+ inst_hook cmdline 00 "$moddir/watchdog.sh"
+ inst_hook cmdline 50 "$moddir/watchdog.sh"
+ inst_hook pre-trigger 00 "$moddir/watchdog.sh"
+ inst_hook initqueue 00 "$moddir/watchdog.sh"
+ inst_hook mount 00 "$moddir/watchdog.sh"
+ inst_hook mount 50 "$moddir/watchdog.sh"
+ inst_hook mount 99 "$moddir/watchdog.sh"
+ inst_hook pre-pivot 00 "$moddir/watchdog.sh"
+ inst_hook pre-pivot 99 "$moddir/watchdog.sh"
+ inst_hook cleanup 00 "$moddir/watchdog.sh"
+ inst_hook cleanup 99 "$moddir/watchdog.sh"
+ fi
+
+ inst_hook emergency 02 "$moddir/watchdog-stop.sh"
+ inst_multiple -o wdctl
+}
diff --git a/modules.d/04watchdog/watchdog-stop.sh b/modules.d/04watchdog/watchdog-stop.sh
new file mode 100755
index 0000000..921f969
--- /dev/null
+++ b/modules.d/04watchdog/watchdog-stop.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+[ -c /dev/watchdog ] && printf 'V' > /dev/watchdog
diff --git a/modules.d/04watchdog/watchdog.sh b/modules.d/04watchdog/watchdog.sh
new file mode 100755
index 0000000..22919ee
--- /dev/null
+++ b/modules.d/04watchdog/watchdog.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+if [ -e /dev/watchdog ]; then
+ if [ ! -e /tmp/watchdog_timeout ]; then
+ wdctl -s 60 /dev/watchdog > /dev/null 2>&1
+ : > /tmp/watchdog_timeout
+ fi
+ info "Triggering watchdog"
+ : > /dev/watchdog
+else
+ modprobe ib700wdt
+ modprobe i6300esb
+fi
diff --git a/modules.d/05busybox/module-setup.sh b/modules.d/05busybox/module-setup.sh
new file mode 100755
index 0000000..86b3761
--- /dev/null
+++ b/modules.d/05busybox/module-setup.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ require_binaries busybox || return 1
+
+ return 255
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+# called by dracut
+install() {
+ local _i _path _busybox
+ local _progs=()
+ _busybox=$(find_binary busybox)
+ inst "$_busybox" /usr/bin/busybox
+ for _i in $($_busybox --list); do
+ [[ ${_i} == busybox ]] && continue
+ _progs+=("${_i}")
+ done
+
+ for _i in "${_progs[@]}"; do
+ _path=$(find_binary "$_i")
+ [ -z "$_path" ] && continue
+ ln_r /usr/bin/busybox "$_path"
+ done
+}
diff --git a/modules.d/06dbus-broker/module-setup.sh b/modules.d/06dbus-broker/module-setup.sh
new file mode 100755
index 0000000..a38fce8
--- /dev/null
+++ b/modules.d/06dbus-broker/module-setup.sh
@@ -0,0 +1,93 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed
+ require_binaries busctl || return 1
+ require_binaries dbus-broker || return 1
+ require_binaries dbus-broker-launch || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+ # This module has external dependency on the systemd module.
+ echo systemd systemd-sysusers
+ # Return 0 to include the dependent systemd module in the initramfs.
+ return 0
+
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+
+ # Create dbus related directories.
+ inst_dir "$dbus"
+ inst_dir "$dbusinterfaces"
+ inst_dir "$dbusservices"
+ inst_dir "$dbussession"
+ inst_dir "$dbussystem"
+ inst_dir "$dbussystemservices"
+ inst_dir "$dbusconfdir"
+ inst_dir "$dbusinterfacesconfdir"
+ inst_dir "$dbusservicesconfdir"
+ inst_dir "$dbussessionconfdir"
+ inst_dir "$dbussystemconfdir"
+ inst_dir "$dbussystemservicesconfdir"
+
+ inst_multiple -o \
+ "$dbus"/session.conf \
+ "$dbus"/system.conf \
+ "$dbussystem"/org.freedesktop.systemd1.conf \
+ "$dbusservicesconfdir"/org.freedesktop.systemd1.service \
+ "$dbussystemservices"/org.freedesktop.systemd1.service \
+ "$sysusers"/dbus.conf \
+ "$systemdcatalog"/dbus-broker.catalog \
+ "$systemdcatalog"/dbus-broker-launch.catalog \
+ "$systemdsystemunitdir"/dbus-broker.service \
+ "$systemduser"/dbus-broker.service \
+ "$systemdsystemunitdir"/dbus.socket \
+ "$systemduser"/dbus.socket \
+ "$systemdsystemunitdir"/sockets.target.wants/dbus.socket \
+ "$systemduser"/sockets.target.wants/dbus.socket \
+ "$systemdsystemunitdir"/dbus.target.wants \
+ busctl dbus-broker dbus-broker-launch
+
+ # Adjusting dependencies for initramfs in the dbus socket unit.
+ # shellcheck disable=SC1004
+ sed -i -e \
+ '/^\[Unit\]/aDefaultDependencies=no\
+ Conflicts=shutdown.target\
+ Before=shutdown.target
+ /^\[Socket\]/aRemoveOnStop=yes' \
+ "$initdir$systemdsystemunitdir/dbus.socket"
+
+ $SYSTEMCTL -q --root "$initdir" enable dbus-broker.service
+
+ # Install the hosts local user configurations if enabled.
+ if [[ $hostonly ]]; then
+ inst_multiple -H -o \
+ "$dbusconfdir"/session.conf \
+ "$dbusconfdir"/system.conf \
+ "$sysusersconfdir"/dbus.conf \
+ "$systemdsystemconfdir"/dbus.socket \
+ "$systemdsystemconfdir"/dbus.socket.d/*.conf \
+ "$systemdsystemconfdir"/dbus-broker.service \
+ "$systemdsystemconfdir"/dbus-broker.service.d/*.conf \
+ "$systemdsystemconfdir"/sockets.target.wants/dbus.socket
+ fi
+
+ # We need to make sure that systemd-tmpfiles-setup.service->dbus.socket
+ # will not wait for local-fs.target to start if swap is encrypted,
+ # this would make dbus wait the timeout for the swap before loading.
+ # This could delay sysinit services that are dependent on dbus.service.
+ sed -i -Ee \
+ '/^After/s/(After[[:space:]]*=.*)(local-fs.target[[:space:]]*)(.*)/\1-\.mount \3/' \
+ "$initdir$systemdsystemunitdir/systemd-tmpfiles-setup.service"
+}
diff --git a/modules.d/06dbus-daemon/module-setup.sh b/modules.d/06dbus-daemon/module-setup.sh
new file mode 100755
index 0000000..8345585
--- /dev/null
+++ b/modules.d/06dbus-daemon/module-setup.sh
@@ -0,0 +1,96 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed
+ require_binaries busctl || return 1
+ require_binaries dbus-daemon || return 1
+ require_binaries dbus-send || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+}
+
+# Module dependency requirements.
+depends() {
+
+ # This module has external dependency on the systemd module.
+ echo systemd
+ # Return 0 to include the dependent systemd module in the initramfs.
+ return 0
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+ # dbus conflicts with dbus-broker.
+ if dracut_module_included "dbus-broker"; then
+ derror "dbus conflicts with dbus-broker in the initramfs."
+ return 1
+ fi
+
+ # Create dbus related directories.
+ inst_dir "$dbus"
+ inst_dir "$dbusinterfaces"
+ inst_dir "$dbusservices"
+ inst_dir "$dbussession"
+ inst_dir "$dbussystem"
+ inst_dir "$dbussystemservices"
+ inst_dir "$dbusconfdir"
+ inst_dir "$dbusinterfacesconfdir"
+ inst_dir "$dbusservicesconfdir"
+ inst_dir "$dbussessionconfdir"
+ inst_dir "$dbussystemconfdir"
+ inst_dir "$dbussystemservicesconfdir"
+
+ inst_multiple -o \
+ "$dbus"/system.conf \
+ "$dbussystem"/org.freedesktop.systemd1.conf \
+ "$dbusservicesconfdir"/org.freedesktop.systemd1.service \
+ "$dbussystemservices"/org.freedesktop.systemd1.service \
+ "$systemdsystemunitdir"/dbus.service \
+ "$systemdsystemunitdir"/dbus.socket \
+ "$systemdsystemunitdir"/dbus.target.wants \
+ busctl dbus-send dbus-daemon
+
+ # Adjusting dependencies for initramfs in the dbus service unit.
+ # shellcheck disable=SC1004
+ sed -i -e \
+ '/^\[Unit\]/aDefaultDependencies=no\
+ Conflicts=shutdown.target\
+ Before=shutdown.target' \
+ "$initdir$systemdsystemunitdir/dbus.service"
+
+ # Adjusting dependencies for initramfs in the dbus socket unit.
+ # shellcheck disable=SC1004
+ sed -i -e \
+ '/^\[Unit\]/aDefaultDependencies=no\
+ Conflicts=shutdown.target\
+ Before=shutdown.target
+ /^\[Socket\]/aRemoveOnStop=yes' \
+ "$initdir$systemdsystemunitdir/dbus.socket"
+
+ # Adding the user and group for dbus
+ grep '^\(d\|message\)bus:' "$dracutsysrootdir"/etc/passwd >> "$initdir/etc/passwd"
+ grep '^\(d\|message\)bus:' "$dracutsysrootdir"/etc/group >> "$initdir/etc/group"
+
+ # Install the hosts local user configurations if enabled.
+ if [[ $hostonly ]]; then
+ inst_multiple -H -o \
+ "$dbusconfdir"/system.conf \
+ "$systemdsystemconfdir"/dbus.socket \
+ "$systemdsystemconfdir"/dbus.socket.d/*.conf \
+ "$systemdsystemconfdir"/dbus.service \
+ "$systemdsystemconfdir"/dbus.service.d/*.conf
+ fi
+
+ # We need to make sure that systemd-tmpfiles-setup.service->dbus.socket
+ # will not wait for local-fs.target to start if swap is encrypted,
+ # this would make dbus wait the timeout for the swap before loading.
+ # This could delay sysinit services that are dependent on dbus.service.
+ sed -i -Ee \
+ '/^After/s/(After[[:space:]]*=.*)(local-fs.target[[:space:]]*)(.*)/\1-\.mount \3/' \
+ "$initdir$systemdsystemunitdir/systemd-tmpfiles-setup.service"
+}
diff --git a/modules.d/06rngd/module-setup.sh b/modules.d/06rngd/module-setup.sh
new file mode 100755
index 0000000..aec8d57
--- /dev/null
+++ b/modules.d/06rngd/module-setup.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
+#
+# Copyright (c) 2019 Red Hat, Inc.
+# Author: Renaud Métrich <rmetrich@redhat.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+check() {
+ # if there's no rngd binary, no go.
+ require_binaries rngd || return 1
+
+ return 0
+}
+
+depends() {
+ echo systemd
+ return 0
+}
+
+install() {
+ inst rngd
+ inst_simple "${moddir}/rngd.service" "${systemdsystemunitdir}/rngd.service"
+ # make sure dependent libs are installed too
+ inst_libdir_file opensc-pkcs11.so
+
+ $SYSTEMCTL -q --root "$initdir" add-wants sysinit.target rngd.service
+}
diff --git a/modules.d/06rngd/rngd.service b/modules.d/06rngd/rngd.service
new file mode 100644
index 0000000..dd5374d
--- /dev/null
+++ b/modules.d/06rngd/rngd.service
@@ -0,0 +1,8 @@
+[Unit]
+Description=Hardware RNG Entropy Gatherer Daemon
+DefaultDependencies=no
+Before=systemd-udevd.service
+ConditionVirtualization=!container
+
+[Service]
+ExecStart=/usr/sbin/rngd -f
diff --git a/modules.d/09dbus/module-setup.sh b/modules.d/09dbus/module-setup.sh
new file mode 100755
index 0000000..679483d
--- /dev/null
+++ b/modules.d/09dbus/module-setup.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+ # We only want to return 255 since this is a meta module.
+ return 255
+}
+
+# Module dependency requirements.
+depends() {
+ local _module
+ # Add a dbus meta dependency based on the module in use.
+ for _module in dbus-daemon dbus-broker; do
+ if dracut_module_included "$_module"; then
+ echo "$_module"
+ return 0
+ fi
+ done
+
+ if check_module "dbus-broker"; then
+ echo "dbus-broker"
+ return 0
+ else
+ echo "dbus-daemon"
+ return 0
+ fi
+
+ return 1
+}
diff --git a/modules.d/10i18n/10-console.rules b/modules.d/10i18n/10-console.rules
new file mode 100644
index 0000000..640b1db
--- /dev/null
+++ b/modules.d/10i18n/10-console.rules
@@ -0,0 +1,2 @@
+# Console initialization - keyboard, font, etc.
+KERNEL=="tty0", RUN+="/sbin/initqueue --onetime --unique --name console_init_$name /lib/udev/console_init $root/$name"
diff --git a/modules.d/10i18n/README b/modules.d/10i18n/README
new file mode 100644
index 0000000..6cbbae9
--- /dev/null
+++ b/modules.d/10i18n/README
@@ -0,0 +1,124 @@
+dracut i18n module
+------------------
+
+INDEX
+
+0. Introduction
+1. Hostonly vs Generic
+2. Configuration
+ 2.1. Variables
+ 2.2. Setting up mappings
+ 2.3. Additional settings
+3. Kernel parameters
+
+~
+
+0. Introduction
+
+i18n module provides internationalization for initramfs at runtime. It
+is intended to be generic across different GNU/Linux distributions.
+
+i18n and keyboard settings are stored in different files among
+distributions. To deal with it avoiding hardcoding those differences in
+the installation script we handle it by mappings between variables used
+by dracut and the ones in the system. Package maintainer is expected to
+create those for his/her distribution and it's appreciated to share it
+with us, so we can include it in source package.
+
+
+1. Hostonly vs Generic
+
+If you invoke dracut with '-H' option, i18n module install script will
+gather variables values from your configuration files using mappings
+provided in "/etc/dracut.conf.d/<foo>.conf". Those variables will be
+put in "etc/vconsole.conf" and "etc/locale.conf" files inside initramfs
+image. Next it will install only declared font, keymaps and so.
+
+When building generic image (dracut without '-H' option), install script
+copies all content of directories: consolefonts, consoletrans, unimaps
+and keymaps to image. Take into account that's about 4 MiB.
+
+
+2. Configuration
+
+2.1. Variables
+
+The following variables are used by i18n install script and at initramfs
+runtime:
+
+ KEYMAP - keyboard translation table loaded by loadkeys
+ KEYTABLE - base name for keyboard translation table; if UNICODE is
+ true, Unicode version will be loaded. Overrides KEYMAP.
+ EXT_KEYMAPS - list of extra keymaps to bo loaded (sep. by space)
+ UNICODE - boolean, indicating UTF-8 mode
+ FONT - console font
+ FONT_MAP - see description of '-m' parameter in setfont manual
+ FONT_UNIMAP - see description of '-u' parameter in setfont manual
+
+The following are appended to EXT_KEYMAPS only during build time:
+
+ UNIKEYMAP
+ GRP_TOGGLE
+
+They were used in 10redhat-i18n module, but not sure of its purpose.
+I'm leaving it in case... The following are taken from the environment:
+
+ LANG
+ LC_ALL
+
+If UNICODE variable is not provided, script indicates if UTF-8 should be
+used on the basis of LANG value (if it ends with ".utf8" or similar).
+
+
+2.2. Setting up mappings
+
+Mappings between variables listed in 2.1. and the ones spread around
+your system are set up in /etc/dracut.conf.d/<foo>.conf. You need to
+assign mappings to i18n_vars. Here's an example:
+
+i18n_vars="/etc/conf.d/keymaps:KEYMAP,EXTENDED_KEYMAPS-EXT_KEYMAPS /etc/conf.d/consolefont:CONSOLEFONT-FONT,CONSOLETRANSLATION-FONT_MAP /etc/rc.conf:UNICODE"
+
+First we've got name of file in host file system tree. After colon
+there's mapping: <from>-<to>. If both variables have the same name you
+can enter just a single, but it's important to specify it! The module
+will source only variables you've listed.
+
+Below there's detailed description in BNF:
+
+<list> ::= <element> | <element> " " <list>
+<element> ::= <conf-file-name> ":" <map-list>
+<map-list> ::= <mapping> | <mapping> "," <map-list>
+<mapping> ::= <src-var> "-" <dst-var> | <src-var>
+
+We assume no whitespace are allowed between symbols.
+<conf-file-name> is a file holding <src-var> in your system.
+<src-var> is a variable holding value of meaning the same as <dst-var>.
+<dst-var> is a variable which will be set up inside initramfs.
+If <dst-var> has the same name as <src-var> we can omit <dst-var>.
+
+Example:
+/etc/conf.d/keymaps:KEYMAP,extended_keymaps-EXT_KEYMAPS
+<list> = /etc/conf.d/keymaps:KEYMAP,extended_keymaps-EXT_KEYMAPS
+<element> = /etc/conf.d/keymaps:KEYMAP,extended_keymaps-EXT_KEYMAPS
+<conf-file-name> = /etc/conf.d/keymaps
+<map-list> = KEYMAP,extended_keymaps-EXT_KEYMAPS
+<mapping> = KEYMAP
+<src-var> = KEYMAP
+<mapping> = extended_keymaps-EXT_KEYMAPS
+<src-var> = extended_keymaps
+<dst-var> = EXT_KEYMAPS
+
+
+2.3. Additional settings
+
+If you encounter following error message: "Directories consolefonts,
+consoletrans, keymaps, unimaps not found.", you can provide path where
+those directories lie in your system by setting kbddir in configuration
+file (the same where you put mappings).
+
+
+3. Kernel parameters
+
+If you create generic initramfs you can set up i18n by kernel
+parameters using variables listed in 2.1. (except of UNIKEYMAP
+and GRP_TOGGLE) The recommended minimum is: FONT and KEYMAP.
diff --git a/modules.d/10i18n/console_init.sh b/modules.d/10i18n/console_init.sh
new file mode 100755
index 0000000..3ca0ac1
--- /dev/null
+++ b/modules.d/10i18n/console_init.sh
@@ -0,0 +1,89 @@
+#!/bin/sh
+
+[ -n "$DRACUT_SYSTEMD" ] && exit 0
+
+if [ -x "$systemdutildir"/systemd-vconsole-setup ]; then
+ "$systemdutildir"/systemd-vconsole-setup "$@"
+fi
+
+[ -e /etc/vconsole.conf ] && . /etc/vconsole.conf
+
+DEFAULT_FONT=eurlatgr
+DEFAULT_KEYMAP=/etc/sysconfig/console/default.kmap
+
+set_keyboard() {
+ local param
+
+ [ "${UNICODE}" = 1 ] && param=-u || param=-a
+ kbd_mode ${param}
+}
+
+set_terminal() {
+ local dev="$1"
+
+ if [ "${UNICODE}" = 1 ]; then
+ printf '\033%%G' >&7
+ stty -F "${dev}" iutf8
+ else
+ printf '\033%%@' >&7
+ stty -F "${dev}" -iutf8
+ fi
+}
+
+set_keymap() {
+ local utf_switch
+
+ if [ -z "${KEYMAP}" ]; then
+ [ -f "${DEFAULT_KEYMAP}" ] && KEYMAP=${DEFAULT_KEYMAP}
+ fi
+
+ [ -n "${KEYMAP}" ] || return 1
+
+ [ "${UNICODE}" = 1 ] && utf_switch=-u
+
+ # shellcheck disable=SC2086
+ loadkeys -q ${utf_switch} ${KEYMAP} ${EXT_KEYMAPS}
+}
+
+set_font() {
+ setfont "${FONT-${DEFAULT_FONT}}" \
+ -C "${1}" \
+ ${FONT_MAP:+-m "${FONT_MAP}"} \
+ ${FONT_UNIMAP:+-u "${FONT_UNIMAP}"}
+}
+
+dev_close() {
+ exec 6>&-
+ exec 7>&-
+}
+
+dev_open() {
+ local dev="$1"
+
+ exec 6< "${dev}" \
+ && exec 7>> "${dev}"
+}
+
+dev=/dev/${1#/dev/}
+
+[ -c "${dev}" ] || {
+ echo "Usage: $0 device" >&2
+ exit 1
+}
+
+dev_open "${dev}"
+
+for fd in 6 7; do
+ if ! [ -t ${fd} ]; then
+ echo "ERROR: File descriptor not opened: ${fd}" >&2
+ dev_close
+ exit 1
+ fi
+done
+
+set_keyboard
+set_terminal "${dev}"
+set_font "${dev}"
+set_keymap
+
+dev_close
diff --git a/modules.d/10i18n/module-setup.sh b/modules.d/10i18n/module-setup.sh
new file mode 100755
index 0000000..ac45611
--- /dev/null
+++ b/modules.d/10i18n/module-setup.sh
@@ -0,0 +1,297 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ [[ "$mount_needs" ]] && return 1
+
+ require_binaries setfont loadkeys kbd_mode || return 1
+
+ return 0
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+# called by dracut
+install() {
+ declare -A KEYMAPS
+
+ if dracut_module_included "systemd"; then
+ unset FONT
+ unset KEYMAP
+ # shellcheck disable=SC1090
+ [[ -f "$dracutsysrootdir"/etc/vconsole.conf ]] && . "$dracutsysrootdir"/etc/vconsole.conf
+ fi
+
+ KBDSUBDIRS=(consolefonts consoletrans keymaps unimaps)
+ DEFAULT_FONT="${i18n_default_font:-eurlatgr}"
+ I18N_CONF="/etc/locale.conf"
+ VCONFIG_CONF="/etc/vconsole.conf"
+
+ findkeymap() {
+ local -a MAPS
+ local MAPNAME
+ local INCLUDES
+ local MAP
+ local CMD
+ local FN
+
+ if [[ -f $dracutsysrootdir$1 ]]; then
+ MAPS=("$1")
+ else
+ MAPNAME=${1%.map*}
+
+ mapfile -t -d '' MAPS < <(
+ find "${dracutsysrootdir}${kbddir}"/keymaps/ -type f \( -name "${MAPNAME}" -o -name "${MAPNAME}.map*" \) -print0
+ )
+ fi
+
+ for MAP in "${MAPS[@]}"; do
+ [[ -f $MAP ]] || continue
+ [[ -v KEYMAPS["$MAP"] ]] && continue
+
+ KEYMAPS["$MAP"]=1
+
+ case "$MAP" in
+ *.gz) CMD="zgrep" ;;
+ *.bz2) CMD="bzgrep" ;;
+ *) CMD="grep" ;;
+ esac
+
+ readarray -t INCLUDES < <("$CMD" '^include ' "$MAP" | while read -r _ a _ || [ -n "$a" ]; do echo "${a//\"/}"; done)
+
+ for INCL in "${INCLUDES[@]}"; do
+ local -a FNS
+ mapfile -t -d '' FNS < <(find "${dracutsysrootdir}${kbddir}"/keymaps/ -type f -name "${INCL}*" -print0)
+ for FN in "${FNS[@]}"; do
+ [[ -f $FN ]] || continue
+ [[ -v KEYMAPS["$FN"] ]] || findkeymap "$FN"
+ done
+ done
+ done
+ }
+
+ # Function gathers variables from distributed files among the tree, maps to
+ # specified names and prints the result in format "new-name=value".
+ #
+ # $@ = list in format specified below (BNF notation)
+ #
+ # <list> ::= <element> | <element> " " <list>
+ # <element> ::= <conf-file-name> ":" <map-list>
+ # <map-list> ::= <mapping> | <mapping> "," <map-list>
+ # <mapping> ::= <src-var> "-" <dst-var> | <src-var>
+ #
+ # We assume no whitespace are allowed between symbols.
+ # <conf-file-name> is a file holding <src-var> in your system.
+ # <src-var> is a variable holding value of meaning the same as <dst-var>.
+ # <dst-var> is a variable which will be set up inside initramfs.
+ # If <dst-var> has the same name as <src-var> we can omit <dst-var>.
+ #
+ # Example:
+ # /etc/conf.d/keymaps:KEYMAP,extended_keymaps-EXT_KEYMAPS
+ # <list> = /etc/conf.d/keymaps:KEYMAP,extended_keymaps-EXT_KEYMAPS
+ # <element> = /etc/conf.d/keymaps:KEYMAP,extended_keymaps-EXT_KEYMAPS
+ # <conf-file-name> = /etc/conf.d/keymaps
+ # <map-list> = KEYMAP,extended_keymaps-EXT_KEYMAPS
+ # <mapping> = KEYMAP
+ # <src-var> = KEYMAP
+ # <mapping> = extended_keymaps-EXT_KEYMAPS
+ # <src-var> = extended_keymaps
+ # <dst-var> = EXT_KEYMAPS
+ gather_vars() {
+ local item map value
+
+ # FIXME: double check
+ # shellcheck disable=SC2068
+ for item in "$@"; do
+ read -r -a item <<< "${item/:/ }"
+ for map in ${item[1]//,/ }; do
+ read -r -a map <<< "${map//-/ }"
+ if [[ -f "$dracutsysrootdir${item[0]}" ]]; then
+ value=$(grep "^${map[0]}=" "$dracutsysrootdir${item[0]}")
+ value=${value#*=}
+ echo "${map[1]:-${map[0]}}=${value}"
+ fi
+ unset map
+ done
+ done
+ }
+
+ install_base() {
+ inst_multiple setfont loadkeys kbd_mode stty
+
+ if ! dracut_module_included "systemd"; then
+ inst "${moddir}"/console_init.sh /lib/udev/console_init
+ inst_rules "${moddir}"/10-console.rules
+ inst_hook cmdline 20 "${moddir}/parse-i18n.sh"
+ fi
+
+ if [[ ${kbddir} != "/usr/share" ]]; then
+ inst_dir /usr/share
+ for _src in "${KBDSUBDIRS[@]}"; do
+ [ ! -e "${initdir}/usr/share/${_src}" ] && ln -s "${kbddir}/${_src}" "${initdir}/usr/share/${_src}"
+ done
+ fi
+ }
+
+ install_all_kbd() {
+ local _src _line
+
+ for _src in "${KBDSUBDIRS[@]}"; do
+ inst_dir "${kbddir}/$_src"
+ $DRACUT_CP -L -t "${initdir}/${kbddir}/$_src" "${dracutsysrootdir}${kbddir}/$_src"/*
+ done
+
+ # remove unnecessary files
+ rm -f -- "${initdir}${kbddir}/consoletrans/utflist"
+ find "${initdir}${kbddir}/" -name README\* -delete
+ find "${initdir}${kbddir}/" -name '*.gz' -print -quit \
+ | while read -r _line || [ -n "$_line" ]; do
+ inst_multiple gzip
+ done
+
+ find "${initdir}${kbddir}/" -name '*.bz2' -print -quit \
+ | while read -r _line || [ -n "$_line" ]; do
+ inst_multiple bzip2
+ done
+ }
+
+ install_local_i18n() {
+ local map
+
+ # shellcheck disable=SC2086
+ eval "$(gather_vars ${i18n_vars})"
+ # shellcheck disable=SC1090
+ [ -f "$dracutsysrootdir"$I18N_CONF ] && . "$dracutsysrootdir"$I18N_CONF
+ # shellcheck disable=SC1090
+ [ -f "$dracutsysrootdir"$VCONFIG_CONF ] && . "$dracutsysrootdir"$VCONFIG_CONF
+
+ shopt -q -s nocasematch
+ if [[ ${UNICODE} ]]; then
+ if [[ ${UNICODE} == YES || ${UNICODE} == 1 ]]; then
+ UNICODE=1
+ elif [[ ${UNICODE} == NO || ${UNICODE} == 0 ]]; then
+ UNICODE=0
+ else
+ UNICODE=''
+ fi
+ fi
+ if [[ ! ${UNICODE} && ${LANG} =~ .*\.UTF-?8 ]]; then
+ UNICODE=1
+ fi
+ shopt -q -u nocasematch
+
+ # Gentoo user may have KEYMAP set to something like "-u pl2",
+ KEYMAP=${KEYMAP#-* }
+
+ # openSUSE user may have KEYMAP set to something like ".gz"
+ KEYMAP=${KEYMAP/.gz/}
+
+ # KEYTABLE is a bit special - it defines base keymap name and UNICODE
+ # determines whether non-UNICODE or UNICODE version is used
+
+ if [[ ${KEYTABLE} ]]; then
+ if [[ ${UNICODE} == 1 ]]; then
+ [[ ${KEYTABLE} =~ .*\.uni.* ]] || KEYTABLE=${KEYTABLE%.map*}.uni
+ fi
+ KEYMAP=${KEYTABLE}
+ fi
+
+ # I'm not sure of the purpose of UNIKEYMAP and GRP_TOGGLE. They were in
+ # original redhat-i18n module. Anyway it won't hurt.
+ EXT_KEYMAPS+=\ ${UNIKEYMAP}\ ${GRP_TOGGLE}
+
+ [[ ${KEYMAP} ]] || {
+ dinfo 'No KEYMAP configured.'
+ return 1
+ }
+
+ findkeymap "${KEYMAP}"
+
+ for map in ${EXT_KEYMAPS}; do
+ ddebug "Adding extra map: ${map}"
+ findkeymap "${map}"
+ done
+
+ for keymap in "${!KEYMAPS[@]}"; do
+ inst_opt_decompress "${keymap}"
+ done
+
+ inst_opt_decompress "${kbddir}"/consolefonts/"${DEFAULT_FONT}".*
+
+ if [[ ${FONT} ]] && [[ ${FONT} != "${DEFAULT_FONT}" ]]; then
+ if [[ -f "${kbddir}"/consolefonts/"${FONT}" ]]; then
+ inst_opt_decompress "${kbddir}"/consolefonts/"${FONT}"
+ else
+ FONT=${FONT%.psf*}
+ inst_opt_decompress "${kbddir}"/consolefonts/"${FONT}".*
+ fi
+ fi
+
+ if [[ ${FONT_MAP} ]]; then
+ FONT_MAP=${FONT_MAP%.trans}
+ # There are three different formats that setfont supports
+ inst_simple "${kbddir}"/consoletrans/"${FONT_MAP}" \
+ || inst_simple "${kbddir}"/consoletrans/"${FONT_MAP}".trans \
+ || inst_simple "${kbddir}"/consoletrans/"${FONT_MAP}"_to_uni.trans \
+ || dwarn "Could not find FONT_MAP ${FONT_MAP}!"
+ fi
+
+ if [[ ${FONT_UNIMAP} ]]; then
+ FONT_UNIMAP=${FONT_UNIMAP%.uni}
+ inst_simple "${kbddir}"/unimaps/"${FONT_UNIMAP}".uni
+ fi
+
+ if dracut_module_included "systemd" && [[ -f $dracutsysrootdir${I18N_CONF} ]]; then
+ inst_simple ${I18N_CONF}
+ else
+ mksubdirs "${initdir}"${I18N_CONF}
+ print_vars LC_ALL LANG >> "${initdir}"${I18N_CONF}
+ fi
+
+ if ! dracut_module_included "systemd"; then
+ mksubdirs "${initdir}"${VCONFIG_CONF}
+ print_vars KEYMAP EXT_KEYMAPS UNICODE FONT FONT_MAP FONT_UNIMAP >> "${initdir}"${VCONFIG_CONF}
+ fi
+
+ return 0
+ }
+
+ checks() {
+ for kbddir in ${kbddir} /usr/lib/kbd /lib/kbd /usr/share /usr/share/kbd; do
+ if [[ -d "$dracutsysrootdir${kbddir}" ]]; then
+ for dir in "${KBDSUBDIRS[@]}"; do
+ [[ -d "$dracutsysrootdir${kbddir}/${dir}" ]] && continue
+ false
+ done && break
+ fi
+ kbddir=''
+ done
+
+ [[ "$kbddir" ]] || return 1
+
+ [[ -f $dracutsysrootdir$I18N_CONF && -f $dracutsysrootdir$VCONFIG_CONF ]] \
+ || [[ ! ${hostonly} || ${i18n_vars} ]] || {
+ derror 'i18n_vars not set! Please set up i18n_vars in ' \
+ 'configuration file.'
+ }
+ return 0
+ }
+
+ if checks; then
+ install_base
+
+ # https://github.com/dracutdevs/dracut/issues/796
+ if dracut_module_included "systemd" && [[ -f $dracutsysrootdir${VCONFIG_CONF} ]]; then
+ inst_simple ${VCONFIG_CONF}
+ fi
+
+ if [[ ${hostonly} ]] && ! [[ ${i18n_install_all} == "yes" ]]; then
+ install_local_i18n || install_all_kbd
+ else
+ install_all_kbd
+ fi
+ fi
+}
diff --git a/modules.d/10i18n/parse-i18n.sh b/modules.d/10i18n/parse-i18n.sh
new file mode 100755
index 0000000..2deb2c4
--- /dev/null
+++ b/modules.d/10i18n/parse-i18n.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+inst_key_val() {
+ local _value
+ local _file
+ local _default
+ _file="$1"
+ shift
+ _key="$1"
+ shift
+ _default="$1"
+ shift
+ _value="$(getarg "$@")"
+ [ -z "${_value}" ] && _value=$_default
+ if [ -n "${_value}" ]; then
+ printf -- '%s="%s"\n' "${_key}" "${_value}" >> "$_file"
+ fi
+ unset _file
+ unset _value
+}
+
+inst_key_val /etc/vconsole.conf KEYMAP '' rd.vconsole.keymap KEYMAP -d KEYTABLE
+inst_key_val /etc/vconsole.conf FONT '' rd.vconsole.font FONT -d SYSFONT
+inst_key_val /etc/vconsole.conf FONT_MAP '' rd.vconsole.font.map FONT_MAP -d CONTRANS
+inst_key_val /etc/vconsole.conf FONT_UNIMAP '' rd.vconsole.font.unimap FONT_UNIMAP -d UNIMAP
+inst_key_val /etc/vconsole.conf UNICODE 1 rd.vconsole.font.unicode UNICODE vconsole.unicode
+inst_key_val /etc/vconsole.conf EXT_KEYMAP '' rd.vconsole.keymap.ext EXT_KEYMAP
+
+inst_key_val /etc/locale.conf LANG '' rd.locale.LANG LANG
+inst_key_val /etc/locale.conf LC_ALL '' rd.locale.LC_ALL LC_ALL
+
+if [ -f /etc/locale.conf ]; then
+ . /etc/locale.conf
+ export LANG
+ export LC_ALL
+fi
diff --git a/modules.d/30convertfs/convertfs.sh b/modules.d/30convertfs/convertfs.sh
new file mode 100755
index 0000000..58fa56d
--- /dev/null
+++ b/modules.d/30convertfs/convertfs.sh
@@ -0,0 +1,193 @@
+#!/bin/bash
+
+type ismounted > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+ROOT="$1"
+
+if [[ ! -d $ROOT ]]; then
+ echo "Usage: $0 <rootdir>"
+ exit 1
+fi
+
+if [[ $ROOT -ef / ]]; then
+ echo "Can't convert the running system."
+ echo "Please boot with 'rd.convertfs' on the kernel command line,"
+ echo "to update with the help of the initramfs,"
+ echo "or run this script from a rescue system."
+ exit 1
+fi
+
+while [[ $ROOT != "${ROOT%/}" ]]; do
+ ROOT=${ROOT%/}
+done
+
+if [ ! -L "$ROOT"/var/run -a -e "$ROOT"/var/run ]; then
+ echo "Converting /var/run to symlink"
+ mv -f "$ROOT"/var/run "$ROOT"/var/run.runmove~
+ ln -sfn ../run "$ROOT"/var/run
+fi
+
+if [ ! -L "$ROOT"/var/lock -a -e "$ROOT"/var/lock ]; then
+ echo "Converting /var/lock to symlink"
+ mv -f "$ROOT"/var/lock "$ROOT"/var/lock.lockmove~
+ ln -sfn ../run/lock "$ROOT"/var/lock
+fi
+
+needconvert() {
+ for dir in "$ROOT/bin" "$ROOT/sbin" "$ROOT/lib" "$ROOT/lib64"; do
+ if [[ -e $dir ]]; then
+ [[ -L $dir ]] || return 0
+ fi
+ done
+ return 1
+}
+
+if ! [ -e "$ROOT/usr/bin" ]; then
+ echo "$ROOT/usr/bin does not exist!"
+ echo "Make sure, the kernel command line has enough information"
+ echo "to mount /usr (man dracut.cmdline)"
+ exit 1
+fi
+
+if ! needconvert; then
+ echo "Your system is already converted."
+ exit 0
+fi
+
+testfile="$ROOT/.usrmovecheck$$"
+rm -f -- "$testfile"
+: > "$testfile"
+if [[ ! -e $testfile ]]; then
+ echo "Cannot write to $ROOT/"
+ exit 1
+fi
+rm -f -- "$testfile"
+
+testfile="$ROOT/usr/.usrmovecheck$$"
+rm -f -- "$testfile"
+: > "$testfile"
+if [[ ! -e $testfile ]]; then
+ echo "Cannot write to $ROOT/usr/"
+ exit 1
+fi
+rm -f -- "$testfile"
+
+find_mount() {
+ local dev wanted_dev
+ wanted_dev="$(readlink -e -q "$1")"
+ while read -r dev _ || [ -n "$dev" ]; do
+ [ "$dev" = "$wanted_dev" ] && echo "$dev" && return 0
+ done < /proc/mounts
+ return 1
+}
+
+# clean up after ourselves no matter how we die.
+cleanup() {
+ echo "Something failed. Move back to the original state"
+ for dir in "$ROOT/bin" "$ROOT/sbin" "$ROOT/lib" "$ROOT/lib64" \
+ "$ROOT/usr/bin" "$ROOT/usr/sbin" "$ROOT/usr/lib" \
+ "$ROOT/usr/lib64"; do
+ [[ -d "${dir}.usrmove-new" ]] && rm -fr -- "${dir}.usrmove-new"
+ if [[ -d "${dir}.usrmove-old" ]]; then
+ mv "$dir" "${dir}.del~"
+ mv "${dir}.usrmove-old" "$dir"
+ rm -fr -- "${dir}.del~"
+ fi
+ done
+}
+
+trap 'ret=$?; [[ $ret -ne 0 ]] && cleanup;exit $ret;' EXIT
+trap 'exit 1;' SIGINT
+
+ismounted "$ROOT/usr" || CP_HARDLINK="-l"
+
+set -e
+
+# merge / and /usr in new dir in /usr
+for dir in bin sbin lib lib64; do
+ rm -rf -- "$ROOT/usr/${dir}.usrmove-new"
+ [[ -L "$ROOT/$dir" ]] && continue
+ [[ -d "$ROOT/$dir" ]] || continue
+ echo "Make a copy of \`$ROOT/usr/$dir'."
+ [[ -d "$ROOT/usr/$dir" ]] \
+ && cp -ax -l "$ROOT/usr/$dir" "$ROOT/usr/${dir}.usrmove-new"
+ echo "Merge the copy with \`$ROOT/$dir'."
+ [[ -d "$ROOT/usr/${dir}.usrmove-new" ]] \
+ || mkdir -p "$ROOT/usr/${dir}.usrmove-new"
+ cp -axT $CP_HARDLINK --backup --suffix=.usrmove~ "$ROOT/$dir" "$ROOT/usr/${dir}.usrmove-new"
+ echo "Clean up duplicates in \`$ROOT/usr/$dir'."
+ # delete all symlinks that have been backed up
+ find "$ROOT/usr/${dir}.usrmove-new" -type l -name '*.usrmove~' -delete || :
+ # replace symlink with backed up binary
+ # shellcheck disable=SC2156
+ find "$ROOT/usr/${dir}.usrmove-new" \
+ -name '*.usrmove~' \
+ -type f \
+ -exec bash -c 'p="{}";o=${p%%%%.usrmove~};
+ [[ -L "$o" ]] && mv -f "$p" "$o"' ';' || :
+done
+# switch over merged dirs in /usr
+for dir in bin sbin lib lib64; do
+ [[ -d "$ROOT/usr/${dir}.usrmove-new" ]] || continue
+ echo "Switch to new \`$ROOT/usr/$dir'."
+ rm -fr -- "$ROOT/usr/${dir}.usrmove-old"
+ mv "$ROOT/usr/$dir" "$ROOT/usr/${dir}.usrmove-old"
+ mv "$ROOT/usr/${dir}.usrmove-new" "$ROOT/usr/$dir"
+done
+
+# replace dirs in / with links to /usr
+for dir in bin sbin lib lib64; do
+ [[ -L "$ROOT/$dir" ]] && continue
+ [[ -d "$ROOT/$dir" ]] || continue
+ echo "Create \`$ROOT/$dir' symlink."
+ rm -fr -- "$ROOT/${dir}.usrmove-old" || :
+ mv "$ROOT/$dir" "$ROOT/${dir}.usrmove-old"
+ ln -sfn usr/$dir "$ROOT/$dir"
+done
+
+echo "Clean up backup files."
+# everything seems to work; cleanup
+for dir in bin sbin lib lib64; do
+ # if we get killed in the middle of "rm -rf", ensure not to leave
+ # an incomplete directory, which is moved back by cleanup()
+ [[ -d "$ROOT/usr/${dir}.usrmove-old" ]] \
+ && mv "$ROOT/usr/${dir}.usrmove-old" "$ROOT/usr/${dir}.usrmove-old~"
+ [[ -d "$ROOT/${dir}.usrmove-old" ]] \
+ && mv "$ROOT/${dir}.usrmove-old" "$ROOT/${dir}.usrmove-old~"
+done
+
+for dir in bin sbin lib lib64; do
+ if [[ -d "$ROOT/usr/${dir}.usrmove-old~" ]]; then
+ rm -rf -- "$ROOT/usr/${dir}.usrmove-old~"
+ fi
+
+ if [[ -d "$ROOT/${dir}.usrmove-old~" ]]; then
+ rm -rf -- "$ROOT/${dir}.usrmove-old~"
+ fi
+done
+
+for dir in lib lib64; do
+ [[ -d "$ROOT/$dir" ]] || continue
+ for lib in "$ROOT"/usr/"${dir}"/lib*.so*.usrmove~; do
+ [[ -f $lib ]] || continue
+ mv "$lib" "${lib/.so/_so}"
+ done
+done
+
+set +e
+
+echo "Run ldconfig."
+ldconfig -r "$ROOT"
+
+if [[ -f "$ROOT"/etc/selinux/config ]]; then
+ # shellcheck disable=SC1090
+ . "$ROOT"/etc/selinux/config
+fi
+
+if [ -n "$(command -v setfiles)" ] && [ "$SELINUX" != "disabled" ] && [ -f /etc/selinux/"${SELINUXTYPE}"/contexts/files/file_contexts ]; then
+ echo "Fixing SELinux labels"
+ setfiles -r "$ROOT" -p /etc/selinux/"${SELINUXTYPE}"/contexts/files/file_contexts "$ROOT"/sbin "$ROOT"/bin "$ROOT"/lib "$ROOT"/lib64 "$ROOT"/usr/lib "$ROOT"/usr/lib64 "$ROOT"/etc/ld.so.cache "$ROOT"/var/cache/ldconfig || :
+fi
+
+echo "Done."
+exit 0
diff --git a/modules.d/30convertfs/do-convertfs.sh b/modules.d/30convertfs/do-convertfs.sh
new file mode 100755
index 0000000..6ce31cb
--- /dev/null
+++ b/modules.d/30convertfs/do-convertfs.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+if getargbool 0 rd.convertfs; then
+ if getargbool 0 rd.debug; then
+ bash -x convertfs "$NEWROOT" 2>&1 | vinfo
+ else
+ convertfs "$NEWROOT" 2>&1 | vinfo
+ fi
+fi
diff --git a/modules.d/30convertfs/module-setup.sh b/modules.d/30convertfs/module-setup.sh
new file mode 100755
index 0000000..68fb78f
--- /dev/null
+++ b/modules.d/30convertfs/module-setup.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ [[ $mount_needs ]] && return 1
+ return 255
+}
+
+# called by dracut
+depends() {
+ echo base bash
+}
+
+# called by dracut
+install() {
+ inst_multiple bash find ldconfig mv rm cp ln
+ inst_hook pre-pivot 99 "$moddir/do-convertfs.sh"
+ inst_script "$moddir/convertfs.sh" /usr/bin/convertfs
+}
diff --git a/modules.d/35connman/cm-config.sh b/modules.d/35connman/cm-config.sh
new file mode 100755
index 0000000..6ae754a
--- /dev/null
+++ b/modules.d/35connman/cm-config.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+type cm_generate_connections > /dev/null 2>&1 || . /lib/cm-lib.sh
+
+if [ -n "$netroot" ] || [ -e /tmp/net.ifaces ]; then
+ echo rd.neednet >> /etc/cmdline.d/connman.conf
+fi
+
+if getargbool 0 rd.debug -d -y rdinitdebug -d -y rdnetdebug; then
+ if [ -n "$DRACUT_SYSTEMD" ]; then
+ # Enable tty output if a usable console is found
+ # shellcheck disable=SC2217
+ if [ -w /dev/console ] && (echo < /dev/console) > /dev/null 2> /dev/null; then
+ mkdir -p /run/systemd/system/cm-initrd.service.d
+ cat << EOF > /run/systemd/system/cm-initrd.service.d/tty-output.conf
+[Service]
+StandardOutput=tty
+EOF
+ systemctl --no-block daemon-reload
+ fi
+ fi
+fi
+
+cm_generate_connections
diff --git a/modules.d/35connman/cm-initrd.service b/modules.d/35connman/cm-initrd.service
new file mode 100644
index 0000000..cecb408
--- /dev/null
+++ b/modules.d/35connman/cm-initrd.service
@@ -0,0 +1,24 @@
+[Unit]
+DefaultDependencies=no
+Wants=systemd-udev-trigger.service
+After=systemd-udev-trigger.service
+After=dracut-cmdline.service
+Wants=network.target
+Before=network.target
+RequiresMountsFor=/var/lib/connman
+After=dbus.service
+ConditionPathExists=/run/connman/initrd/neednet
+
+[Service]
+Type=dbus
+BusName=net.connman
+Restart=on-failure
+ExecStart=/usr/sbin/connmand -n
+StandardOutput=null
+CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SYS_TIME CAP_SYS_MODULE CAP_SYS_ADMIN
+ProtectHome=true
+ProtectSystem=full
+
+[Install]
+WantedBy=initrd.target
+Also=cm-wait-online-initrd.service
diff --git a/modules.d/35connman/cm-lib.sh b/modules.d/35connman/cm-lib.sh
new file mode 100755
index 0000000..69c4fa2
--- /dev/null
+++ b/modules.d/35connman/cm-lib.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+type getcmdline > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+cm_generate_connections() {
+ if getargbool 0 rd.neednet; then
+ mkdir -p "$hookdir"/initqueue/finished
+ echo '[ -f /tmp/cm.done ]' > "$hookdir"/initqueue/finished/cm.sh
+ mkdir -p /run/connman/initrd
+ : > /run/connman/initrd/neednet # activate ConnMan services
+ fi
+}
diff --git a/modules.d/35connman/cm-run.sh b/modules.d/35connman/cm-run.sh
new file mode 100755
index 0000000..a9dcf05
--- /dev/null
+++ b/modules.d/35connman/cm-run.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+type source_hook > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+if [ -e /tmp/cm.done ]; then
+ return
+fi
+
+while read -r _serv; do
+ ifname=$(connmanctl services "$_serv" | grep Interface= | sed 's/^.*Interface=\([^,]*\).*$/\1/')
+ source_hook initqueue/online "$ifname"
+ /sbin/netroot "$ifname"
+done < <(connmanctl services | grep -oE '[^ ]+$')
+
+: > /tmp/cm.done
diff --git a/modules.d/35connman/cm-wait-online-initrd.service b/modules.d/35connman/cm-wait-online-initrd.service
new file mode 100644
index 0000000..08e6941
--- /dev/null
+++ b/modules.d/35connman/cm-wait-online-initrd.service
@@ -0,0 +1,16 @@
+[Unit]
+DefaultDependencies=no
+Requires=cm-initrd.service
+After=cm-initrd.service
+Before=network-online.target
+Before=dracut-initqueue.service
+ConditionPathExists=/run/connman/initrd/neednet
+
+[Service]
+Type=oneshot
+ExecStart=/usr/sbin/connmand-wait-online
+RemainAfterExit=yes
+
+[Install]
+WantedBy=initrd.target
+WantedBy=network-online.target
diff --git a/modules.d/35connman/module-setup.sh b/modules.d/35connman/module-setup.sh
new file mode 100755
index 0000000..6502d30
--- /dev/null
+++ b/modules.d/35connman/module-setup.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ require_binaries sed grep connmand connmanctl connmand-wait-online || return 1
+
+ # do not add this module by default
+ return 255
+}
+
+# called by dracut
+depends() {
+ echo dbus systemd bash
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ return 0
+}
+
+# called by dracut
+install() {
+ # We don't need `ip` but having it is *really* useful for people debugging
+ # in an emergency shell.
+ inst_multiple ip sed grep
+
+ inst_script "$moddir/netroot.sh" "/sbin/netroot"
+ inst connmand
+ inst connmanctl
+ inst connmand-wait-online
+ inst "$dbussystem"/connman.conf
+ [[ $hostonly ]] && [[ -f $dracutsysrootdir/etc/connman/main.conf ]] && inst /etc/connman/main.conf
+ inst_dir /usr/lib/connman/plugins
+ inst_dir /var/lib/connman
+
+ inst_hook cmdline 99 "$moddir/cm-config.sh"
+
+ inst_simple "$moddir"/cm-initrd.service "$systemdsystemunitdir"/cm-initrd.service
+ inst_simple "$moddir"/cm-wait-online-initrd.service "$systemdsystemunitdir"/cm-wait-online-initrd.service
+
+ $SYSTEMCTL -q --root "$initdir" enable cm-initrd.service
+
+ inst_hook initqueue/settled 99 "$moddir/cm-run.sh"
+
+ inst_simple "$moddir/cm-lib.sh" "/lib/cm-lib.sh"
+}
diff --git a/modules.d/35connman/netroot.sh b/modules.d/35connman/netroot.sh
new file mode 100755
index 0000000..8f97774
--- /dev/null
+++ b/modules.d/35connman/netroot.sh
@@ -0,0 +1,92 @@
+#!/bin/sh
+
+PATH=/usr/sbin:/usr/bin:/sbin:/bin
+command -v getarg > /dev/null || . /lib/dracut-lib.sh
+command -v setup_net > /dev/null || . /lib/net-lib.sh
+
+# Huh? Empty $1?
+[ -z "$1" ] && exit 1
+
+# [ ! -z $2 ] means this is for manually bringing up network
+# instead of real netroot; If It's called without $2, then there's
+# no sense in doing something if no (net)root info is available
+# or root is already there
+[ -d "$NEWROOT"/proc ] && exit 0
+
+if [ -z "$netroot" ]; then
+ netroot=$(getarg netroot=)
+fi
+
+[ -z "$netroot" ] && exit 1
+
+# Set or override primary interface
+netif=$1
+[ -e "/tmp/net.bootdev" ] && read -r netif < /tmp/net.bootdev
+
+case "$netif" in
+ ??:??:??:??:??:??) # MAC address
+ for i in /sys/class/net/*/address; do
+ read -r mac < "$i"
+ if [ "$mac" = "$netif" ]; then
+ i=${i%/address}
+ netif=${i##*/}
+ break
+ fi
+ done ;;
+esac
+
+# Figure out the handler for root=dhcp by recalling all netroot cmdline
+# handlers when this is not called from manually network bringing up.
+if [ -z "$2" ]; then
+ if getarg "root=dhcp" || getarg "netroot=dhcp" || getarg "root=dhcp6" || getarg "netroot=dhcp6"; then
+ # Load dhcp options
+ # shellcheck disable=SC1090
+ [ -e /tmp/dhclient."$netif".dhcpopts ] && . /tmp/dhclient."$netif".dhcpopts
+
+ # If we have a specific bootdev with no dhcpoptions or empty root-path,
+ # we die. Otherwise we just warn
+ if [ -z "$new_root_path" ]; then
+ [ -n "$BOOTDEV" ] && die "No dhcp root-path received for '$BOOTDEV'"
+ warn "No dhcp root-path received for '$netif' trying other interfaces if available"
+ exit 1
+ fi
+
+ rm -f -- "$hookdir"/initqueue/finished/dhcp.sh
+
+ # Set netroot to new_root_path, so cmdline parsers don't call
+ netroot=$new_root_path
+
+ # FIXME!
+ unset rootok
+ for f in "$hookdir"/cmdline/90*.sh; do
+ # shellcheck disable=SC1090
+ [ -f "$f" ] && . "$f"
+ done
+ else
+ rootok="1"
+ fi
+
+ # Check: do we really know how to handle (net)root?
+ if [ -z "$root" ]; then
+ root=$(getarg root=)
+ fi
+ [ -z "$root" ] && die "No or empty root= argument"
+ [ -z "$rootok" ] && die "Don't know how to handle 'root=$root'"
+
+ handler=${netroot%%:*}
+ handler=${handler%%4}
+ handler=$(command -v "${handler}"root)
+ if [ -z "$netroot" ] || [ ! -e "$handler" ]; then
+ die "No handler for netroot type '$netroot'"
+ fi
+fi
+
+# Source netroot hooks before we start the handler
+source_hook netroot "$netif"
+
+# Run the handler; don't store the root, it may change from device to device
+# XXX other variables to export?
+[ -n "$handler" ] && "$handler" "$netif" "$netroot" "$NEWROOT"
+save_netinfo "$netif"
+
+exit 0
diff --git a/modules.d/35network-legacy/dhclient-script.sh b/modules.d/35network-legacy/dhclient-script.sh
new file mode 100755
index 0000000..b3e5e75
--- /dev/null
+++ b/modules.d/35network-legacy/dhclient-script.sh
@@ -0,0 +1,275 @@
+#!/bin/sh
+
+PATH=/usr/sbin:/usr/bin:/sbin:/bin
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+type ip_to_var > /dev/null 2>&1 || . /lib/net-lib.sh
+
+# We already need a set netif here
+netif=$interface
+
+setup_interface() {
+ ip=$new_ip_address
+ mtu=$new_interface_mtu
+ mask=$new_subnet_mask
+ bcast=$new_broadcast_address
+ gw=${new_routers%%,*}
+ domain=$new_domain_name
+ # get rid of control chars
+ search=$(printf -- "%s" "$new_domain_search" | tr -d '[:cntrl:]')
+ namesrv=$new_domain_name_servers
+ hostname=$new_host_name
+ [ -n "$new_dhcp_lease_time" ] && lease_time=$new_dhcp_lease_time
+ [ -n "$new_max_life" ] && lease_time=$new_max_life
+ preferred_lft=$lease_time
+ [ -n "$new_preferred_life" ] && preferred_lft=$new_preferred_life
+
+ # shellcheck disable=SC1090
+ [ -f /tmp/net."$netif".override ] && . /tmp/net."$netif".override
+
+ # Taken from debian dhclient-script:
+ # The 576 MTU is only used for X.25 and dialup connections
+ # where the admin wants low latency. Such a low MTU can cause
+ # problems with UDP traffic, among other things. As such,
+ # disallow MTUs from 576 and below by default, so that broken
+ # MTUs are ignored, but higher stuff is allowed (1492, 1500, etc).
+ if [ -n "$mtu" ] && [ "$mtu" -gt 576 ]; then
+ if ! ip link set "$netif" mtu "$mtu"; then
+ ip link set "$netif" down
+ ip link set "$netif" mtu "$mtu"
+ linkup "$netif"
+ fi
+ fi
+
+ ip addr add "$ip"${mask:+/$mask} ${bcast:+broadcast $bcast} dev "$netif" \
+ ${lease_time:+valid_lft $lease_time} \
+ ${preferred_lft:+preferred_lft ${preferred_lft}}
+
+ if [ -n "$gw" ]; then
+ if [ "$mask" = "255.255.255.255" ]; then
+ # point-to-point connection => set explicit route to gateway
+ echo ip route add "$gw" dev "$netif" > /tmp/net."$netif".gw
+ fi
+
+ echo "$gw" | {
+ IFS=' ' read -r main_gw other_gw
+ echo ip route replace default via "$main_gw" dev "$netif" >> /tmp/net."$netif".gw
+ if [ -n "$other_gw" ]; then
+ for g in $other_gw; do
+ echo ip route add default via "$g" dev "$netif" >> /tmp/net."$netif".gw
+ done
+ fi
+ }
+ fi
+
+ if getargbool 1 rd.peerdns; then
+ [ -n "${search}${domain}" ] && echo "search $search $domain" > /tmp/net."$netif".resolv.conf
+ if [ -n "$namesrv" ]; then
+ for s in $namesrv; do
+ echo nameserver "$s"
+ done
+ fi >> /tmp/net."$netif".resolv.conf
+ fi
+ # Note: hostname can be fqdn OR short hostname, so chop off any
+ # trailing domain name and explicitly add any domain if set.
+ [ -n "$hostname" ] && echo "echo ${hostname%."$domain"}${domain:+.$domain} > /proc/sys/kernel/hostname" > /tmp/net."$netif".hostname
+}
+
+setup_interface6() {
+ domain=$new_domain_name
+ # get rid of control chars
+ search=$(printf -- "%s" "$new_dhcp6_domain_search" | tr -d '[:cntrl:]')
+ namesrv=$new_dhcp6_name_servers
+ hostname=$new_host_name
+ [ -n "$new_dhcp_lease_time" ] && lease_time=$new_dhcp_lease_time
+ [ -n "$new_max_life" ] && lease_time=$new_max_life
+ preferred_lft=$lease_time
+ [ -n "$new_preferred_life" ] && preferred_lft=$new_preferred_life
+
+ # shellcheck disable=SC1090
+ [ -f /tmp/net."$netif".override ] && . /tmp/net."$netif".override
+
+ ip -6 addr add "${new_ip6_address}"/"${new_ip6_prefixlen}" \
+ dev "${netif}" scope global \
+ ${lease_time:+valid_lft $lease_time} \
+ ${preferred_lft:+preferred_lft ${preferred_lft}}
+
+ if getargbool 1 rd.peerdns; then
+ [ -n "${search}${domain}" ] && echo "search $search $domain" > /tmp/net."$netif".resolv.conf
+ if [ -n "$namesrv" ]; then
+ for s in $namesrv; do
+ echo nameserver "$s"
+ done
+ fi >> /tmp/net."$netif".resolv.conf
+ fi
+
+ # Note: hostname can be fqdn OR short hostname, so chop off any
+ # trailing domain name and explicitly add any domain if set.
+ [ -n "$hostname" ] && echo "echo ${hostname%."$domain"}${domain:+.$domain} > /proc/sys/kernel/hostname" > /tmp/net."$netif".hostname
+}
+
+parse_option_121() {
+ while [ $# -ne 0 ]; do
+ mask="$1"
+ shift
+
+ # Is the destination a multicast group?
+ if [ "$1" -ge 224 -a "$1" -lt 240 ]; then
+ multicast=1
+ else
+ multicast=0
+ fi
+
+ # Parse the arguments into a CIDR net/mask string
+ if [ "$mask" -gt 24 ]; then
+ destination="$1.$2.$3.$4/$mask"
+ shift
+ shift
+ shift
+ shift
+ elif [ "$mask" -gt 16 ]; then
+ destination="$1.$2.$3.0/$mask"
+ shift
+ shift
+ shift
+ elif [ "$mask" -gt 8 ]; then
+ destination="$1.$2.0.0/$mask"
+ shift
+ shift
+ elif [ "$mask" -gt 0 ]; then
+ destination="$1.0.0.0/$mask"
+ shift
+ else
+ destination="0.0.0.0/$mask"
+ fi
+
+ # Read the gateway
+ gateway="$1.$2.$3.$4"
+ shift
+ shift
+ shift
+ shift
+
+ # Multicast routing on Linux
+ # - If you set a next-hop address for a multicast group, this breaks with Cisco switches
+ # - If you simply leave it link-local and attach it to an interface, it works fine.
+ if [ $multicast -eq 1 -o "$gateway" = "0.0.0.0" ]; then
+ temp_result="$destination dev $interface"
+ else
+ temp_result="$destination via $gateway dev $interface"
+ fi
+
+ echo "/sbin/ip route replace $temp_result"
+ done
+}
+
+case $reason in
+ PREINIT)
+ echo "dhcp: PREINIT $netif up"
+ linkup "$netif"
+ ;;
+
+ PREINIT6)
+ echo "dhcp: PREINIT6 $netif up"
+ linkup "$netif"
+ wait_for_ipv6_dad_link "$netif"
+ ;;
+
+ BOUND)
+ echo "dhcp: BOUND setting up $netif"
+ unset layer2
+ if [ -f /sys/class/net/"$netif"/device/layer2 ]; then
+ read -r layer2 < /sys/class/net/"$netif"/device/layer2
+ fi
+ if [ "$layer2" != "0" ]; then
+ if command -v arping2 > /dev/null; then
+ if arping2 -q -C 1 -c 2 -I "$netif" -0 "$new_ip_address"; then
+ warn "Duplicate address detected for $new_ip_address while doing dhcp. retrying"
+ exit 1
+ fi
+ else
+ if ! arping -f -q -D -c 2 -I "$netif" "$new_ip_address"; then
+ warn "Duplicate address detected for $new_ip_address while doing dhcp. retrying"
+ exit 1
+ fi
+ fi
+ fi
+ unset layer2
+ setup_interface
+ set | while read -r line || [ -n "$line" ]; do
+ [ "${line#new_}" = "$line" ] && continue
+ echo "$line"
+ done > /tmp/dhclient."$netif".dhcpopts
+
+ {
+ echo '. /lib/net-lib.sh'
+ echo "setup_net $netif"
+ if [ -n "$new_classless_static_routes" ]; then
+ OLDIFS="$IFS"
+ IFS=".$IFS"
+ parse_option_121 "$new_classless_static_routes"
+ IFS="$OLDIFS"
+ fi
+ echo "source_hook initqueue/online $netif"
+ [ -e /tmp/net."$netif".manualup ] || echo "/sbin/netroot $netif"
+ echo "rm -f -- $hookdir/initqueue/setup_net_$netif.sh"
+ } > "$hookdir"/initqueue/setup_net_"$netif".sh
+
+ echo "[ -f /tmp/net.$netif.did-setup ]" > "$hookdir"/initqueue/finished/dhclient-"$netif".sh
+ : > /tmp/net."$netif".up
+ if [ -e /sys/class/net/"${netif}"/address ]; then
+ : > "/tmp/net.$(cat /sys/class/net/"${netif}"/address).up"
+ fi
+
+ ;;
+
+ RENEW | REBIND)
+ unset lease_time
+ [ -n "$new_dhcp_lease_time" ] && lease_time=$new_dhcp_lease_time
+ [ -n "$new_max_life" ] && lease_time=$new_max_life
+ preferred_lft=$lease_time
+ [ -n "$new_preferred_life" ] && preferred_lft=$new_preferred_life
+ ip -4 addr change "${new_ip_address}"/"${new_subnet_mask}" broadcast "${new_broadcast_address}" dev "${interface}" \
+ ${lease_time:+valid_lft $lease_time} ${preferred_lft:+preferred_lft ${preferred_lft}} \
+ > /dev/null 2>&1
+ ;;
+
+ BOUND6)
+ echo "dhcp: BOUND6 setting up $netif"
+ setup_interface6
+
+ set | while read -r line || [ -n "$line" ]; do
+ [ "${line#new_}" = "$line" ] && continue
+ echo "$line"
+ done > /tmp/dhclient."$netif".dhcpopts
+
+ {
+ echo '. /lib/net-lib.sh'
+ echo "setup_net $netif"
+ echo "source_hook initqueue/online $netif"
+ [ -e /tmp/net."$netif".manualup ] || echo "/sbin/netroot $netif"
+ echo "rm -f -- $hookdir/initqueue/setup_net_$netif.sh"
+ } > "$hookdir"/initqueue/setup_net_"$netif".sh
+
+ echo "[ -f /tmp/net.$netif.did-setup ]" > "$hookdir"/initqueue/finished/dhclient-"$netif".sh
+ : > /tmp/net."$netif".up
+ if [ -e /sys/class/net/"${netif}"/address ]; then
+ : > "/tmp/net.$(cat /sys/class/net/"${netif}"/address).up"
+ fi
+ ;;
+
+ RENEW6 | REBIND6)
+ unset lease_time
+ [ -n "$new_dhcp_lease_time" ] && lease_time=$new_dhcp_lease_time
+ [ -n "$new_max_life" ] && lease_time=$new_max_life
+ preferred_lft=$lease_time
+ [ -n "$new_preferred_life" ] && preferred_lft=$new_preferred_life
+ ip -6 addr change "${new_ip6_address}"/"${new_ip6_prefixlen}" dev "${interface}" scope global \
+ ${lease_time:+valid_lft $lease_time} ${preferred_lft:+preferred_lft ${preferred_lft}} \
+ > /dev/null 2>&1
+ ;;
+
+ *) echo "dhcp: $reason" ;;
+esac
+
+exit 0
diff --git a/modules.d/35network-legacy/dhclient.conf b/modules.d/35network-legacy/dhclient.conf
new file mode 100644
index 0000000..ffd24ef
--- /dev/null
+++ b/modules.d/35network-legacy/dhclient.conf
@@ -0,0 +1,11 @@
+
+option classless-static-routes code 121 = array of unsigned integer 8;
+
+send dhcp-client-identifier = hardware;
+
+request subnet-mask, broadcast-address, time-offset, routers,
+ domain-name, domain-name-servers, domain-search, host-name,
+ root-path, interface-mtu, classless-static-routes,
+ netbios-name-servers, netbios-scope, ntp-servers,
+ dhcp6.domain-search, dhcp6.fqdn,
+ dhcp6.name-servers, dhcp6.sntp-servers;
diff --git a/modules.d/35network-legacy/dhcp-multi.sh b/modules.d/35network-legacy/dhcp-multi.sh
new file mode 100755
index 0000000..60e0374
--- /dev/null
+++ b/modules.d/35network-legacy/dhcp-multi.sh
@@ -0,0 +1,133 @@
+#!/bin/sh
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+#
+PATH=/usr/sbin:/usr/bin:/sbin:/bin
+
+# File to start dhclient requests on different interfaces in parallel
+
+. /lib/dracut-lib.sh
+. /lib/net-lib.sh
+
+netif=$1
+do_vlan=$2
+arg=$3
+
+# Run dhclient in parallel
+do_dhclient() {
+ local _COUNT=0
+ local _timeout
+ local _DHCPRETRY
+ _timeout=$(getarg rd.net.timeout.dhcp=)
+ _DHCPRETRY=$(getargnum 1 1 1000000000 rd.net.dhcp.retry=)
+
+ if [ -n "$_timeout" ]; then
+ if ! (dhclient --help 2>&1 | grep -q -F -- '--timeout' 2> /dev/null); then
+ warn "rd.net.timeout.dhcp has no effect because dhclient does not implement the --timeout option"
+ unset _timeout
+ fi
+ fi
+
+ while [ $_COUNT -lt "$_DHCPRETRY" ]; do
+ info "Starting dhcp for interface $netif"
+ dhclient "$arg" \
+ ${_timeout:+--timeout "$_timeout"} \
+ -q \
+ -1 \
+ -cf /etc/dhclient.conf \
+ -pf /tmp/dhclient."$netif".pid \
+ -lf /tmp/dhclient."$netif".lease \
+ "$netif" &
+ wait $! 2> /dev/null
+
+ # wait will return the return value of dhclient
+ retv=$?
+
+ # dhclient and hence wait returned success, 0.
+ if [ $retv -eq 0 ]; then
+ return 0
+ fi
+
+ # If dhclient exited before wait was called, or it was killed by
+ # another thread for interface whose DHCP succeeded, then it will not
+ # find the process with that pid and return error code 127. In that
+ # case we need to check if /tmp/dhclient.$netif.lease exists. If it
+ # does, it means dhclient finished executing before wait was called,
+ # and it was successful (return 0). If /tmp/dhclient.$netif.lease
+ # does not exist, then it means dhclient was killed by another thread
+ # or it finished execution but failed dhcp on that interface.
+
+ if [ $retv -eq 127 ]; then
+ read -r pid < /tmp/dhclient."$netif".pid
+ info "PID $pid was not found by wait for $netif"
+ if [ -e /tmp/dhclient."$netif".lease ]; then
+ info "PID $pid not found but DHCP successful on $netif"
+ return 0
+ fi
+ fi
+
+ _COUNT=$((_COUNT + 1))
+ [ $_COUNT -lt "$_DHCPRETRY" ] && sleep 1
+ done
+ warn "dhcp for interface $netif failed"
+ # nuke those files since we failed; we might retry dhcp again if it's e.g.
+ # `ip=dhcp,dhcp6` and we check for the PID file earlier
+ rm -f /tmp/dhclient."$netif".pid /tmp/dhclient."$netif".lease
+ return 1
+}
+
+do_dhclient
+ret=$?
+
+# setup nameserver
+for s in "$dns1" "$dns2" $(getargs nameserver); do
+ [ -n "$s" ] || continue
+ echo nameserver "$s" >> /tmp/net."$netif".resolv.conf
+done
+
+if [ $ret -eq 0 ]; then
+ : > /tmp/net."${netif}".up
+
+ if [ -z "$do_vlan" ] && [ -e /sys/class/net/"${netif}"/address ]; then
+ : > "/tmp/net.$(cat /sys/class/net/"${netif}"/address).up"
+ fi
+
+ # Check if DHCP also succeeded on another interface before this one.
+ # We will always use the first one on which DHCP succeeded, by using
+ # a common file $IFNETFILE, to synchronize between threads.
+ # Consider the race condition in which multiple threads
+ # corresponding to different interfaces may try to read $IFNETFILE
+ # and find it does not exist; they may all end up thinking they are the
+ # first to succeed (hence more than one thread may end up writing to
+ # $IFNETFILE). To take care of this, instead of checking if $IFNETFILE
+ # exists to determine if we are the first, we create a symbolic link
+ # in $IFNETFILE, pointing to the interface name ($netif), thus storing
+ # the interface name in the link pointer.
+ # Creating a link will fail, if the link already exists, hence kernel
+ # will take care of allowing only first thread to create link, which
+ # takes care of the race condition for us. Subsequent threads will fail.
+ # Also, the link points to the interface name, which will tell us which
+ # interface succeeded.
+
+ if ln -s "$netif" "$IFNETFILE" 2> /dev/null; then
+ intf=$(readlink "$IFNETFILE")
+ if [ -e /tmp/dhclient."$intf".lease ]; then
+ info "DHCP successful on interface $intf"
+ # Kill all existing dhclient calls for other interfaces, since we
+ # already got one successful interface
+
+ read -r npid < /tmp/dhclient."$netif".pid
+ pidlist=$(pgrep dhclient)
+ for pid in $pidlist; do
+ [ "$pid" -eq "$npid" ] && continue
+ kill -9 "$pid" > /dev/null 2>&1
+ done
+ else
+ echo "ERROR! $IFNETFILE exists but /tmp/dhclient.$intf.lease does not exist!!!"
+ fi
+ else
+ info "DHCP success on $netif, and also on $intf"
+ exit 0
+ fi
+ exit $ret
+fi
diff --git a/modules.d/35network-legacy/ifup.sh b/modules.d/35network-legacy/ifup.sh
new file mode 100755
index 0000000..3b54b6c
--- /dev/null
+++ b/modules.d/35network-legacy/ifup.sh
@@ -0,0 +1,563 @@
+#!/bin/sh
+#
+# We don't need to check for ip= errors here, that is handled by the
+# cmdline parser script
+#
+# without $2 means this is for real netroot case
+# or it is for manually bring up network ie. for kdump scp vmcore
+PATH=/usr/sbin:/usr/bin:/sbin:/bin
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+type ip_to_var > /dev/null 2>&1 || . /lib/net-lib.sh
+
+# Huh? No $1?
+[ -z "$1" ] && exit 1
+
+# $netif reads easier than $1
+netif=$1
+
+# loopback is always handled the same way
+if [ "$netif" = "lo" ]; then
+ ip link set lo up
+ ip addr add 127.0.0.1/8 dev lo
+ exit 0
+fi
+
+do_dhcp_parallel() {
+ # dhclient-script will mark the netif up and generate the online
+ # event for nfsroot
+ # XXX add -V vendor class and option parsing per kernel
+
+ [ -e "/tmp/dhclient.$netif.pid" ] && return 0
+
+ if ! iface_has_carrier "$netif"; then
+ warn "No carrier detected on interface $netif"
+ return 1
+ fi
+
+ bootintf=$(readlink "$IFNETFILE")
+ if [ -n "$bootintf" ] && [ -e "/tmp/dhclient.${bootintf}.lease" ]; then
+ info "DHCP already succeeded for $bootintf, exiting for $netif"
+ return 1
+ fi
+
+ if [ ! -e /run/NetworkManager/conf.d/10-dracut-dhclient.conf ]; then
+ mkdir -p /run/NetworkManager/conf.d
+ echo '[main]' > /run/NetworkManager/conf.d/10-dracut-dhclient.conf
+ echo 'dhcp=dhclient' >> /run/NetworkManager/conf.d/10-dracut-dhclient.conf
+ fi
+
+ chmod +x /sbin/dhcp-multi.sh
+ /sbin/dhcp-multi.sh "$netif" "$DO_VLAN" "$@" &
+ return 0
+}
+
+# Run dhclient
+do_dhcp() {
+ # dhclient-script will mark the netif up and generate the online
+ # event for nfsroot
+ # XXX add -V vendor class and option parsing per kernel
+
+ local _COUNT
+ local _timeout
+ local _DHCPRETRY
+
+ _COUNT=0
+ _timeout=$(getarg rd.net.timeout.dhcp=)
+ _DHCPRETRY=$(getargnum 1 1 1000000000 rd.net.dhcp.retry=)
+
+ [ -e "/tmp/dhclient.${netif}.pid" ] && return 0
+
+ if ! iface_has_carrier "$netif"; then
+ warn "No carrier detected on interface $netif"
+ return 1
+ fi
+
+ if [ -n "$_timeout" ]; then
+ if ! (dhclient --help 2>&1 | grep -q -F -- '--timeout' 2> /dev/null); then
+ warn "rd.net.timeout.dhcp has no effect because dhclient does not implement the --timeout option"
+ unset _timeout
+ fi
+ fi
+
+ if [ ! -e /run/NetworkManager/conf.d/10-dracut-dhclient.conf ]; then
+ mkdir -p /run/NetworkManager/conf.d
+ echo '[main]' > /run/NetworkManager/conf.d/10-dracut-dhclient.conf
+ echo 'dhcp=dhclient' >> /run/NetworkManager/conf.d/10-dracut-dhclient.conf
+ fi
+
+ while [ "$_COUNT" -lt "$_DHCPRETRY" ]; do
+ info "Starting dhcp for interface $netif"
+ dhclient "$@" \
+ ${_timeout:+--timeout "$_timeout"} \
+ -q \
+ -1 \
+ -cf /etc/dhclient.conf \
+ -pf "/tmp/dhclient.${netif}.pid" \
+ -lf "/tmp/dhclient.${netif}.lease" \
+ "$netif" \
+ && return 0
+ _COUNT=$((_COUNT + 1))
+ [ "$_COUNT" -lt "$_DHCPRETRY" ] && sleep 1
+ done
+ warn "dhcp for interface $netif failed"
+ # nuke those files since we failed; we might retry dhcp again if it's e.g.
+ # `ip=dhcp,dhcp6` and we check for the PID file at the top
+ rm -f /tmp/dhclient."$netif".pid /tmp/dhclient."$netif".lease
+ return 1
+}
+
+load_ipv6() {
+ [ -d /proc/sys/net/ipv6 ] && return
+ modprobe ipv6
+ i=0
+ while [ ! -d /proc/sys/net/ipv6 ]; do
+ i=$((i + 1))
+ [ $i -gt 10 ] && break
+ sleep 0.1
+ done
+}
+
+do_ipv6auto() {
+ local ret
+ load_ipv6
+ echo 0 > /proc/sys/net/ipv6/conf/"${netif}"/forwarding
+ echo 1 > /proc/sys/net/ipv6/conf/"${netif}"/accept_ra
+ echo 1 > /proc/sys/net/ipv6/conf/"${netif}"/accept_redirects
+ linkup "$netif"
+ wait_for_ipv6_auto "$netif"
+ ret=$?
+
+ [ -n "$hostname" ] && echo "echo $hostname > /proc/sys/kernel/hostname" > "/tmp/net.${netif}.hostname"
+
+ return "$ret"
+}
+
+do_ipv6link() {
+ local ret
+ load_ipv6
+ echo 0 > /proc/sys/net/ipv6/conf/"${netif}"/forwarding
+ echo 0 > /proc/sys/net/ipv6/conf/"${netif}"/accept_ra
+ echo 0 > /proc/sys/net/ipv6/conf/"${netif}"/accept_redirects
+ linkup "$netif"
+
+ [ -n "$hostname" ] && echo "echo $hostname > /proc/sys/kernel/hostname" > "/tmp/net.${netif}.hostname"
+
+ return "$ret"
+}
+
+# Handle static ip configuration
+do_static() {
+ strglobin "$ip" '*:*:*' && load_ipv6
+
+ if ! iface_has_carrier "$netif"; then
+ warn "No carrier detected on interface $netif"
+ return 1
+ elif ! linkup "$netif"; then
+ warn "Could not bring interface $netif up!"
+ return 1
+ fi
+
+ ip route get "$ip" 2> /dev/null | {
+ read -r a rest
+ if [ "$a" = "local" ]; then
+ warn "Not assigning $ip to interface $netif, cause it is already assigned!"
+ return 1
+ fi
+ return 0
+ } || return 1
+
+ [ -n "$macaddr" ] && ip link set address "$macaddr" dev "$netif"
+ [ -n "$mtu" ] && ip link set mtu "$mtu" dev "$netif"
+ if strglobin "$ip" '*:*:*'; then
+ # note no ip addr flush for ipv6
+ ip addr add "$ip/$mask" ${srv:+peer "$srv"} dev "$netif"
+ echo 0 > /proc/sys/net/ipv6/conf/"${netif}"/forwarding
+ echo 1 > /proc/sys/net/ipv6/conf/"${netif}"/accept_ra
+ echo 1 > /proc/sys/net/ipv6/conf/"${netif}"/accept_redirects
+ wait_for_ipv6_dad "$netif"
+ else
+ if [ -z "$srv" ]; then
+ if command -v arping2 > /dev/null; then
+ if arping2 -q -C 1 -c 2 -I "$netif" -0 "$ip"; then
+ warn "Duplicate address detected for $ip for interface $netif."
+ return 1
+ fi
+ else
+ if ! arping -f -q -D -c 2 -I "$netif" "$ip"; then
+ warn "Duplicate address detected for $ip for interface $netif."
+ return 1
+ fi
+ fi
+ fi
+ ip addr flush dev "$netif"
+ ip addr add "$ip/$mask" ${srv:+peer "$srv"} brd + dev "$netif"
+ fi
+
+ [ -n "$gw" ] && echo "ip route replace default via '$gw' dev '$netif'" > "/tmp/net.$netif.gw"
+ [ -n "$hostname" ] && echo "echo '$hostname' > /proc/sys/kernel/hostname" > "/tmp/net.$netif.hostname"
+
+ return 0
+}
+
+get_vid() {
+ case "$1" in
+ vlan*)
+ echo "${1#vlan}"
+ ;;
+ *.*)
+ echo "${1##*.}"
+ ;;
+ esac
+}
+
+# check, if we need VLAN's for this interface
+if [ -z "$DO_VLAN_PHY" ] && [ -e "/tmp/vlan.${netif}.phy" ]; then
+ unset DO_VLAN
+ NO_AUTO_DHCP=yes DO_VLAN_PHY=yes ifup "$netif"
+ modprobe -b -q 8021q
+
+ for i in /tmp/vlan.*."${netif}"; do
+ [ -e "$i" ] || continue
+ unset vlanname
+ unset phydevice
+ # shellcheck disable=SC1090
+ . "$i"
+ if [ -n "$vlanname" ]; then
+ linkup "$phydevice"
+ ip link add dev "$vlanname" link "$phydevice" type vlan id "$(get_vid "$vlanname")"
+ ifup "$vlanname"
+ fi
+ done
+ exit 0
+fi
+
+# Check, if interface is VLAN interface
+if ! [ -e "/tmp/vlan.${netif}.phy" ]; then
+ for i in "/tmp/vlan.${netif}".*; do
+ [ -e "$i" ] || continue
+ export DO_VLAN=yes
+ break
+ done
+fi
+
+# bridge this interface?
+if [ -z "$NO_BRIDGE_MASTER" ]; then
+ for i in /tmp/bridge.*.info; do
+ [ -e "$i" ] || continue
+ unset bridgeslaves
+ unset bridgename
+ # shellcheck disable=SC1090
+ . "$i"
+ for ethname in $bridgeslaves; do
+ [ "$netif" != "$ethname" ] && continue
+
+ NO_BRIDGE_MASTER=yes NO_AUTO_DHCP=yes ifup "$ethname"
+ linkup "$ethname"
+ if [ ! -e "/tmp/bridge.$bridgename.up" ]; then
+ ip link add name "$bridgename" type bridge
+ echo 0 > "/sys/devices/virtual/net/$bridgename/bridge/forward_delay"
+ : > "/tmp/bridge.$bridgename.up"
+ fi
+ ip link set dev "$ethname" master "$bridgename"
+ ifup "$bridgename"
+ exit 0
+ done
+ done
+fi
+
+# enslave this interface to bond?
+if [ -z "$NO_BOND_MASTER" ]; then
+ for i in /tmp/bond.*.info; do
+ [ -e "$i" ] || continue
+ unset bondslaves
+ unset bondname
+ # shellcheck disable=SC1090
+ . "$i"
+ for testslave in $bondslaves; do
+ [ "$netif" != "$testslave" ] && continue
+
+ # already setup
+ [ -e "/tmp/bond.$bondname.up" ] && exit 0
+
+ # wait for all slaves to show up
+ for slave in $bondslaves; do
+ # try to create the slave (maybe vlan or bridge)
+ NO_BOND_MASTER=yes NO_AUTO_DHCP=yes ifup "$slave"
+
+ if ! ip link show dev "$slave" > /dev/null 2>&1; then
+ # wait for the last slave to show up
+ exit 0
+ fi
+ done
+
+ modprobe -q -b bonding
+ echo "+$bondname" > /sys/class/net/bonding_masters 2> /dev/null
+ ip link set "$bondname" down
+
+ # Stolen from ifup-eth
+ # add the bits to setup driver parameters here
+ for arg in $bondoptions; do
+ key=${arg%%=*}
+ value=${arg##*=}
+ # %{value:0:1} is replaced with non-bash specific construct
+ if [ "${key}" = "arp_ip_target" -a "${#value}" != "0" -a "+${value%%+*}" != "+" ]; then
+ OLDIFS=$IFS
+ IFS=','
+ for arp_ip in $value; do
+ echo "+$arp_ip" > "/sys/class/net/${bondname}/bonding/$key"
+ done
+ IFS=$OLDIFS
+ else
+ echo "$value" > "/sys/class/net/${bondname}/bonding/$key"
+ fi
+ done
+
+ linkup "$bondname"
+
+ for slave in $bondslaves; do
+ cat "/sys/class/net/$slave/address" > "/tmp/net.${bondname}.${slave}.hwaddr"
+ ip link set "$slave" down
+ echo "+$slave" > "/sys/class/net/$bondname/bonding/slaves"
+ linkup "$slave"
+ done
+
+ # Set mtu on bond master
+ [ -n "$bondmtu" ] && ip link set mtu "$bondmtu" dev "$bondname"
+
+ # add the bits to setup the needed post enslavement parameters
+ for arg in $bondoptions; do
+ key=${arg%%=*}
+ value=${arg##*=}
+ if [ "${key}" = "primary" ]; then
+ echo "$value" > "/sys/class/net/${bondname}/bonding/$key"
+ fi
+ done
+
+ : > "/tmp/bond.$bondname.up"
+
+ NO_BOND_MASTER=yes ifup "$bondname"
+ exit $?
+ done
+ done
+fi
+
+if [ -z "$NO_TEAM_MASTER" ]; then
+ for i in /tmp/team.*.info; do
+ [ -e "$i" ] || continue
+ unset teammaster
+ unset teamslaves
+ # shellcheck disable=SC1090
+ . "$i"
+ for testslave in $teamslaves; do
+ [ "$netif" != "$testslave" ] && continue
+
+ [ -e "/tmp/team.$teammaster.up" ] && exit 0
+
+ # wait for all slaves to show up
+ for slave in $teamslaves; do
+ # try to create the slave (maybe vlan or bridge)
+ NO_TEAM_MASTER=yes NO_AUTO_DHCP=yes ifup "$slave"
+
+ if ! ip link show dev "$slave" > /dev/null 2>&1; then
+ # wait for the last slave to show up
+ exit 0
+ fi
+ done
+
+ if [ ! -e "/tmp/team.$teammaster.up" ]; then
+ # We shall only bring up those _can_ come up
+ # in case of some slave is gone in active-backup mode
+ working_slaves=""
+ for slave in $teamslaves; do
+ teamdctl "${teammaster}" port present "${slave}" 2> /dev/null \
+ && continue
+ ip link set dev "$slave" up 2> /dev/null
+ if wait_for_if_up "$slave"; then
+ working_slaves="$working_slaves$slave "
+ fi
+ done
+ # Do not add slaves now
+ teamd -d -U -n -N -t "$teammaster" -f "/etc/teamd/${teammaster}.conf"
+ for slave in $working_slaves; do
+ # team requires the slaves to be down before joining team
+ ip link set dev "$slave" down
+ (
+ unset TEAM_PORT_CONFIG
+ read -r _hwaddr < "/sys/class/net/$slave/address"
+ _subchannels=$(iface_get_subchannels "$slave")
+ if [ -n "$_hwaddr" ] && [ -e "/etc/sysconfig/network-scripts/mac-${_hwaddr}.conf" ]; then
+ # shellcheck disable=SC1090
+ . "/etc/sysconfig/network-scripts/mac-${_hwaddr}.conf"
+ elif [ -n "$_subchannels" ] && [ -e "/etc/sysconfig/network-scripts/ccw-${_subchannels}.conf" ]; then
+ # shellcheck disable=SC1090
+ . "/etc/sysconfig/network-scripts/ccw-${_subchannels}.conf"
+ elif [ -e "/etc/sysconfig/network-scripts/ifcfg-${slave}" ]; then
+ # shellcheck disable=SC1090
+ . "/etc/sysconfig/network-scripts/ifcfg-${slave}"
+ fi
+
+ if [ -n "${TEAM_PORT_CONFIG}" ]; then
+ /usr/bin/teamdctl "${teammaster}" port config update "${slave}" "${TEAM_PORT_CONFIG}"
+ fi
+ )
+ teamdctl "$teammaster" port add "$slave"
+ done
+
+ ip link set dev "$teammaster" up
+
+ : > "/tmp/team.$teammaster.up"
+ NO_TEAM_MASTER=yes ifup "$teammaster"
+ exit $?
+ fi
+ done
+ done
+fi
+
+# all synthetic interfaces done.. now check if the interface is available
+if ! ip link show dev "$netif" > /dev/null 2>&1; then
+ exit 1
+fi
+
+# disable manual ifup while netroot is set for simplifying our logic
+# in netroot case we prefer netroot to bringup $netif automatically
+[ -n "$2" -a "$2" = "-m" ] && [ -z "$netroot" ] && manualup="$2"
+
+if [ -n "$manualup" ]; then
+ : > "/tmp/net.$netif.manualup"
+ rm -f "/tmp/net.${netif}.did-setup"
+else
+ [ -e "/tmp/net.${netif}.did-setup" ] && exit 0
+ [ -z "$DO_VLAN" ] \
+ && [ -e "/sys/class/net/$netif/address" ] \
+ && [ -e "/tmp/net.$(cat "/sys/class/net/$netif/address").did-setup" ] && exit 0
+fi
+
+# Specific configuration, spin through the kernel command line
+# looking for ip= lines
+for p in $(getargs ip=); do
+ ip_to_var "$p"
+ # skip ibft
+ [ "$autoconf" = "ibft" ] && continue
+
+ case "$dev" in
+ ??:??:??:??:??:??) # MAC address
+ _dev=$(iface_for_mac "$dev")
+ [ -n "$_dev" ] && dev="$_dev"
+ ;;
+ ??-??-??-??-??-??) # MAC address in BOOTIF form
+ _dev=$(iface_for_mac "$(fix_bootif "$dev")")
+ [ -n "$_dev" ] && dev="$_dev"
+ ;;
+ esac
+
+ # If this option isn't directed at our interface, skip it
+ if [ -n "$dev" ]; then
+ if [ "$dev" != "$netif" ]; then
+ [ ! -e "/sys/class/net/$dev" ] \
+ && warn "Network interface '$dev' does not exist!"
+ continue
+ fi
+ else
+ iface_is_enslaved "$netif" && continue
+ fi
+
+ # Store config for later use
+ for i in ip srv gw mask hostname macaddr mtu dns1 dns2; do
+ eval '[ "$'$i'" ] && echo '$i'="$'$i'"'
+ done > "/tmp/net.$netif.override"
+
+ for autoopt in $(str_replace "$autoconf" "," " "); do
+ case $autoopt in
+ dhcp | on | any)
+ do_dhcp -4
+ ;;
+ single-dhcp)
+ do_dhcp_parallel -4
+ exit 0
+ ;;
+ dhcp6)
+ load_ipv6
+ do_dhcp -6
+ ;;
+ auto6)
+ do_ipv6auto
+ ;;
+ either6)
+ do_ipv6auto || do_dhcp -6
+ ;;
+ link6)
+ do_ipv6link
+ ;;
+ *)
+ do_static
+ ;;
+ esac
+ done
+ ret=$?
+
+ # setup nameserver
+ for s in "$dns1" "$dns2" $(getargs nameserver); do
+ [ -n "$s" ] || continue
+ echo "nameserver $s" >> "/tmp/net.$netif.resolv.conf"
+ done
+
+ if [ $ret -eq 0 ]; then
+ : > "/tmp/net.${netif}.up"
+
+ if [ -z "$DO_VLAN" ] && [ -e "/sys/class/net/${netif}/address" ]; then
+ : > "/tmp/net.$(cat "/sys/class/net/${netif}/address").up"
+ fi
+
+ # and finally, finish interface set up if there isn't already a script
+ # to do so (which is the case in the dhcp path)
+ if [ ! -e "$hookdir/initqueue/setup_net_$netif.sh" ]; then
+ setup_net "$netif"
+ source_hook initqueue/online "$netif"
+ if [ -z "$manualup" ]; then
+ /sbin/netroot "$netif"
+ fi
+ fi
+
+ exit $ret
+ fi
+done
+
+# no ip option directed at our interface?
+if [ -z "$NO_AUTO_DHCP" ] && [ ! -e "/tmp/net.${netif}.up" ]; then
+ ret=1
+ if [ -e /tmp/net.bootdev ]; then
+ read -r BOOTDEV < /tmp/net.bootdev
+ if [ "$netif" = "$BOOTDEV" ] || [ "$BOOTDEV" = "$(cat "/sys/class/net/${netif}/address")" ]; then
+ do_dhcp
+ ret=$?
+ fi
+ else
+ # No ip lines, no bootdev -> default to dhcp
+ ip=$(getarg ip)
+
+ if getargs 'ip=dhcp6' > /dev/null || [ -z "$ip" -a "$netroot" = "dhcp6" ]; then
+ load_ipv6
+ do_dhcp -6
+ ret=$?
+ fi
+ if getargs 'ip=dhcp' > /dev/null || [ -z "$ip" -a "$netroot" != "dhcp6" ]; then
+ do_dhcp -4
+ ret=$?
+ fi
+ fi
+
+ for s in $(getargs nameserver); do
+ [ -n "$s" ] || continue
+ echo "nameserver $s" >> "/tmp/net.$netif.resolv.conf"
+ done
+
+ if [ "$ret" -eq 0 ] && [ -n "$(ls "/tmp/leaseinfo.${netif}"* 2> /dev/null)" ]; then
+ : > "/tmp/net.${netif}.did-setup"
+ if [ -e "/sys/class/net/${netif}/address" ]; then
+ : > "/tmp/net.$(cat "/sys/class/net/${netif}/address").did-setup"
+ fi
+ fi
+fi
+
+exit 0
diff --git a/modules.d/35network-legacy/kill-dhclient.sh b/modules.d/35network-legacy/kill-dhclient.sh
new file mode 100755
index 0000000..9ed615f
--- /dev/null
+++ b/modules.d/35network-legacy/kill-dhclient.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+for f in /tmp/dhclient.*.pid; do
+ [ -e "$f" ] || continue
+ read -r PID < "$f"
+ kill "$PID" > /dev/null 2>&1
+done
+
+sleep 0.1
+
+for f in /tmp/dhclient.*.pid; do
+ [ -e "$f" ] || continue
+ read -r PID < "$f"
+ kill -9 "$PID" > /dev/null 2>&1
+done
diff --git a/modules.d/35network-legacy/module-setup.sh b/modules.d/35network-legacy/module-setup.sh
new file mode 100755
index 0000000..868ea8f
--- /dev/null
+++ b/modules.d/35network-legacy/module-setup.sh
@@ -0,0 +1,99 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ require_binaries ip dhclient sed awk grep pgrep tr expr || return 1
+ require_any_binary arping arping2 || return 1
+
+ return 255
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ # arping depends on af_packet
+ hostonly='' instmods af_packet
+}
+
+# called by dracut
+install() {
+ local _arch
+
+ #Adding default link
+ if dracut_module_included "systemd"; then
+ inst_multiple -o "${systemdnetwork}/99-default.link"
+ [[ $hostonly ]] && inst_multiple -H -o "${systemdnetworkconfdir}/*.link"
+ fi
+
+ inst_multiple ip dhclient sed awk grep pgrep tr expr
+
+ inst_multiple -o arping arping2
+ strstr "$(arping 2>&1)" "ARPing 2" && mv "$initdir/bin/arping" "$initdir/bin/arping2"
+
+ inst_multiple -o ping ping6
+ inst_multiple -o teamd teamdctl teamnl
+ inst_simple /etc/libnl/classid
+ inst_script "$moddir/ifup.sh" "/sbin/ifup"
+ inst_script "$moddir/dhcp-multi.sh" "/sbin/dhcp-multi.sh"
+ inst_script "$moddir/dhclient-script.sh" "/sbin/dhclient-script"
+ inst_simple -H "/etc/dhclient.conf"
+ cat "$moddir/dhclient.conf" >> "${initdir}/etc/dhclient.conf"
+ inst_hook pre-udev 60 "$moddir/net-genrules.sh"
+ inst_hook cmdline 92 "$moddir/parse-ibft.sh"
+ inst_hook cmdline 95 "$moddir/parse-vlan.sh"
+ inst_hook cmdline 96 "$moddir/parse-bond.sh"
+ inst_hook cmdline 96 "$moddir/parse-team.sh"
+ inst_hook cmdline 97 "$moddir/parse-bridge.sh"
+ inst_hook cmdline 98 "$moddir/parse-ip-opts.sh"
+ inst_hook cmdline 99 "$moddir/parse-ifname.sh"
+ inst_hook cleanup 10 "$moddir/kill-dhclient.sh"
+
+ # install all config files for teaming
+ unset TEAM_MASTER
+ unset TEAM_CONFIG
+ unset TEAM_PORT_CONFIG
+ unset HWADDR
+ unset SUBCHANNELS
+ for i in /etc/sysconfig/network-scripts/ifcfg-*; do
+ [ -e "$i" ] || continue
+ case "$i" in
+ *~ | *.bak | *.orig | *.rpmnew | *.rpmorig | *.rpmsave)
+ continue
+ ;;
+ esac
+ (
+ # shellcheck disable=SC1090
+ . "$i"
+ if ! [ "${ONBOOT}" = "no" -o "${ONBOOT}" = "NO" ] \
+ && [ -n "${TEAM_MASTER}${TEAM_CONFIG}${TEAM_PORT_CONFIG}" ]; then
+ if [ -n "$TEAM_CONFIG" ] && [ -n "$DEVICE" ]; then
+ mkdir -p "$initdir"/etc/teamd
+ printf -- "%s" "$TEAM_CONFIG" > "$initdir/etc/teamd/${DEVICE}.conf"
+ elif [ -n "$TEAM_PORT_CONFIG" ]; then
+ inst_simple "$i"
+
+ HWADDR="$(echo "$HWADDR" | sed 'y/ABCDEF/abcdef/')"
+ if [ -n "$HWADDR" ]; then
+ ln_r "$i" "/etc/sysconfig/network-scripts/mac-${HWADDR}.conf"
+ fi
+
+ SUBCHANNELS="$(echo "$SUBCHANNELS" | sed 'y/ABCDEF/abcdef/')"
+ if [ -n "$SUBCHANNELS" ]; then
+ ln_r "$i" "/etc/sysconfig/network-scripts/ccw-${SUBCHANNELS}.conf"
+ fi
+ fi
+ fi
+ )
+ done
+
+ _arch=${DRACUT_ARCH:-$(uname -m)}
+
+ inst_libdir_file {"tls/$_arch/",tls/,"$_arch/",}"libnss_dns.so.*" \
+ {"tls/$_arch/",tls/,"$_arch/",}"libnss_mdns4_minimal.so.*"
+
+ dracut_need_initqueue
+}
diff --git a/modules.d/35network-legacy/net-genrules.sh b/modules.d/35network-legacy/net-genrules.sh
new file mode 100755
index 0000000..686db59
--- /dev/null
+++ b/modules.d/35network-legacy/net-genrules.sh
@@ -0,0 +1,125 @@
+#!/bin/sh
+
+getargbool 0 rd.neednet && NEEDNET=1
+
+# Don't continue if we don't need network
+if [ -z "$netroot" ] && [ ! -e "/tmp/net.ifaces" ] && [ "$NEEDNET" != "1" ]; then
+ return
+fi
+
+command -v fix_bootif > /dev/null || . /lib/net-lib.sh
+
+# Write udev rules
+{
+ # bridge: attempt only the defined interface
+ for i in /tmp/bridge.*.info; do
+ [ -e "$i" ] || continue
+ unset bridgeslaves
+ unset bridgename
+ # shellcheck disable=SC1090
+ . "$i"
+ RAW_IFACES="$RAW_IFACES $bridgeslaves"
+ MASTER_IFACES="$MASTER_IFACES $bridgename"
+ done
+
+ # bond: attempt only the defined interface (override bridge defines)
+ for i in /tmp/bond.*.info; do
+ [ -e "$i" ] || continue
+ unset bondslaves
+ unset bondname
+ # shellcheck disable=SC1090
+ . "$i"
+ # It is enough to fire up only one
+ RAW_IFACES="$RAW_IFACES $bondslaves"
+ MASTER_IFACES="$MASTER_IFACES ${bondname}"
+ done
+
+ for i in /tmp/team.*.info; do
+ [ -e "$i" ] || continue
+ unset teamslaves
+ unset teammaster
+ # shellcheck disable=SC1090
+ . "$i"
+ RAW_IFACES="$RAW_IFACES ${teamslaves}"
+ MASTER_IFACES="$MASTER_IFACES ${teammaster}"
+ done
+
+ for i in /tmp/vlan.*.phy; do
+ [ -e "$i" ] || continue
+ unset phydevice
+ # shellcheck disable=SC1090
+ . "$i"
+ RAW_IFACES="$RAW_IFACES $phydevice"
+ for j in /tmp/vlan.*".${phydevice}"; do
+ [ -e "$j" ] || continue
+ unset vlanname
+ # shellcheck disable=SC1090
+ . "$j"
+ MASTER_IFACES="$MASTER_IFACES ${vlanname}"
+ done
+ done
+
+ MASTER_IFACES="$(trim "$MASTER_IFACES")"
+ RAW_IFACES="$(trim "$RAW_IFACES")"
+
+ if [ -z "$IFACES" ]; then
+ [ -e /tmp/net.ifaces ] && read -r IFACES < /tmp/net.ifaces
+ fi
+
+ if [ -e /tmp/net.bootdev ]; then
+ read -r bootdev < /tmp/net.bootdev
+ fi
+
+ # shellcheck disable=SC2016
+ ifup='/sbin/ifup $name'
+
+ runcmd="RUN+=\"/sbin/initqueue --name ifup-\$name --unique --onetime $ifup\""
+
+ # We have some specific interfaces to handle
+ if [ -n "${RAW_IFACES}${IFACES}" ]; then
+ echo 'SUBSYSTEM!="net", GOTO="net_end"'
+ echo 'ACTION!="add|change|move", GOTO="net_end"'
+ for iface in $IFACES $RAW_IFACES; do
+ case "$iface" in
+ ??:??:??:??:??:??) # MAC address
+ cond="ATTR{address}==\"$iface\""
+ echo "$cond, $runcmd, GOTO=\"net_end\""
+ ;;
+ ??-??-??-??-??-??) # MAC address in BOOTIF form
+ cond="ATTR{address}==\"$(fix_bootif "$iface")\""
+ echo "$cond, $runcmd, GOTO=\"net_end\""
+ ;;
+ *) # an interface name
+ cond="ENV{INTERFACE}==\"$iface\""
+ echo "$cond, $runcmd, GOTO=\"net_end\""
+ cond="NAME==\"$iface\""
+ echo "$cond, $runcmd, GOTO=\"net_end\""
+ ;;
+ esac
+ # The GOTO prevents us from trying to ifup the same device twice
+ done
+ echo 'LABEL="net_end"'
+
+ for iface in $IFACES; do
+ if [ "$bootdev" = "$iface" ] || [ "$NEEDNET" = "1" ]; then
+ if [ -n "$netroot" ] && [ -n "$DRACUT_SYSTEMD" ]; then
+ echo "systemctl is-active initrd-root-device.target || [ -f /tmp/net.${iface}.did-setup ]"
+ else
+ echo "[ -f /tmp/net.${iface}.did-setup ]"
+ fi > "$hookdir"/initqueue/finished/wait-"$iface".sh
+ fi
+ done
+ # Default: We don't know the interface to use, handle all
+ # Fixme: waiting for the interface as well.
+ else
+ cond='ACTION=="add", SUBSYSTEM=="net", ENV{DEVTYPE}!="wlan|wwan"'
+ # if you change the name of "91-default-net.rules", also change modules.d/80cms/cmssetup.sh
+ echo "$cond, $runcmd" > /etc/udev/rules.d/91-default-net.rules
+ if [ "$NEEDNET" = "1" ]; then
+ # shellcheck disable=SC2016
+ echo 'for i in /tmp/net.*.did-setup; do [ -f "$i" ] && exit 0; done; exit 1' > "$hookdir"/initqueue/finished/wait-network.sh
+ fi
+ fi
+
+ # if you change the name of "90-net.rules", also change modules.d/80cms/cmssetup.sh
+} > /etc/udev/rules.d/90-net.rules
diff --git a/modules.d/35network-legacy/parse-bond.sh b/modules.d/35network-legacy/parse-bond.sh
new file mode 100755
index 0000000..ba30a3b
--- /dev/null
+++ b/modules.d/35network-legacy/parse-bond.sh
@@ -0,0 +1,76 @@
+#!/bin/sh
+#
+# Format:
+# bond=<bondname>[:<bondslaves>[:<options>[:<mtu>]]]
+#
+# bondslaves is a comma-separated list of physical (ethernet) interfaces
+# options is a comma-separated list on bonding options (modinfo bonding for details) in format compatible with initscripts
+# if options include multi-valued arp_ip_target option, then its values should be separated by semicolon.
+#
+# bond without parameters assumes bond=bond0:eth0,eth1:mode=balance-rr
+#
+# if the mtu is specified, it will be set on the bond master
+#
+
+# We translate list of slaves to space-separated here to make it easier to loop over them in ifup
+# Ditto for bonding options
+parsebond() {
+ local v="${1}":
+ set --
+ while [ -n "$v" ]; do
+ set -- "$@" "${v%%:*}"
+ v=${v#*:}
+ done
+
+ case $# in
+ 0)
+ bondname=bond0
+ bondslaves="eth0 eth1"
+ ;;
+ 1)
+ bondname=$1
+ bondslaves="eth0 eth1"
+ ;;
+ 2)
+ bondname=$1
+ bondslaves=$(str_replace "$2" "," " ")
+ ;;
+ 3)
+ bondname=$1
+ bondslaves=$(str_replace "$2" "," " ")
+ bondoptions=$(str_replace "$3" "," " ")
+ ;;
+ 4)
+ bondname=$1
+ bondslaves=$(str_replace "$2" "," " ")
+ bondoptions=$(str_replace "$3" "," " ")
+ bondmtu=$4
+ ;;
+ *) die "bond= requires zero to four parameters" ;;
+ esac
+}
+
+# Parse bond for bondname, bondslaves, bondmode, bondoptions and bondmtu
+for bond in $(getargs bond=); do
+ unset bondname
+ unset bondslaves
+ unset bondoptions
+ unset bondmtu
+ if [ "$bond" != "bond" ]; then
+ parsebond "$bond"
+ fi
+ # Simple default bond
+ if [ -z "$bondname" ]; then
+ bondname=bond0
+ bondslaves="eth0 eth1"
+ fi
+ # Make it suitable for initscripts export
+ bondoptions=$(str_replace "$bondoptions" ";" ",")
+
+ {
+ echo "bondname=$bondname"
+ echo "bondslaves=\"$bondslaves\""
+ echo "bondoptions=\"$bondoptions\""
+ echo "bondmtu=\"$bondmtu\""
+ } > "/tmp/bond.${bondname}.info"
+done
diff --git a/modules.d/35network-legacy/parse-bridge.sh b/modules.d/35network-legacy/parse-bridge.sh
new file mode 100755
index 0000000..caea1da
--- /dev/null
+++ b/modules.d/35network-legacy/parse-bridge.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+#
+# Format:
+# bridge=<bridgename>:<bridgeslaves>
+#
+# <bridgeslaves> is a comma-separated list of physical (ethernet) interfaces
+# bridge without parameters assumes bridge=br0:eth0
+#
+
+parsebridge() {
+ local v="${1}":
+ set --
+ while [ -n "$v" ]; do
+ set -- "$@" "${v%%:*}"
+ v=${v#*:}
+ done
+ case $# in
+ 0)
+ bridgename=br0
+ bridgeslaves=$iface
+ ;;
+ 1) die "bridge= requires two parameters" ;;
+ 2)
+ bridgename=$1
+ bridgeslaves=$(str_replace "$2" "," " ")
+ ;;
+ *) die "bridge= requires two parameters" ;;
+ esac
+}
+
+# Parse bridge for bridgename and bridgeslaves
+for bridge in $(getargs bridge=); do
+ unset bridgename
+ unset bridgeslaves
+ iface=eth0
+ # Read bridge= parameters if they exist
+ if [ "$bridge" != "bridge" ]; then
+ parsebridge "$bridge"
+ fi
+ # Simple default bridge
+ if [ -z "$bridgename" ]; then
+ bridgename=br0
+ bridgeslaves=$iface
+ fi
+ {
+ echo "bridgename=$bridgename"
+ echo "bridgeslaves=\"$bridgeslaves\""
+ } > /tmp/bridge.${bridgename}.info
+done
diff --git a/modules.d/35network-legacy/parse-ibft.sh b/modules.d/35network-legacy/parse-ibft.sh
new file mode 100755
index 0000000..1937f13
--- /dev/null
+++ b/modules.d/35network-legacy/parse-ibft.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+command -v getarg > /dev/null || . /lib/dracut-lib.sh
+command -v ibft_to_cmdline > /dev/null || . /lib/net-lib.sh
+
+if getargbool 0 rd.iscsi.ibft -d "ip=ibft"; then
+ modprobe -b -q iscsi_boot_sysfs 2> /dev/null
+ modprobe -b -q iscsi_ibft
+ ibft_to_cmdline
+fi
diff --git a/modules.d/35network-legacy/parse-ifname.sh b/modules.d/35network-legacy/parse-ifname.sh
new file mode 100755
index 0000000..be7b6ad
--- /dev/null
+++ b/modules.d/35network-legacy/parse-ifname.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# Format:
+# ifname=<interface>:<mac>
+#
+# Note letters in the macaddress must be lowercase!
+#
+# Examples:
+# ifname=eth0:4a:3f:4c:04:f8:d7
+#
+# Note when using ifname= to get persistent interface names, you must specify
+# an ifname= argument for each interface used in an ip= or fcoe= argument
+
+# check if there are any ifname parameters
+if ! getarg ifname= > /dev/null; then
+ return
+fi
+
+command -v parse_ifname_opts > /dev/null || . /lib/net-lib.sh
+
+# Check ifname= lines
+for p in $(getargs ifname=); do
+ parse_ifname_opts "$p"
+done
diff --git a/modules.d/35network-legacy/parse-ip-opts.sh b/modules.d/35network-legacy/parse-ip-opts.sh
new file mode 100755
index 0000000..8263321
--- /dev/null
+++ b/modules.d/35network-legacy/parse-ip-opts.sh
@@ -0,0 +1,151 @@
+#!/bin/sh
+#
+# Format:
+# ip=[dhcp|on|any|single-dhcp]
+#
+# ip=<interface>:[dhcp|on|any][:[<mtu>][:<macaddr>]]
+#
+# ip=<client-IP-number>:<server-IP-number>:<gateway-IP-number>:<netmask>:<client-hostname>:<interface>:{dhcp|on|any|none|off}[:[<mtu>][:<macaddr>]]
+#
+# When supplying more than only ip= line, <interface> is mandatory and
+# bootdev= must contain the name of the primary interface to use for
+# routing,dns,dhcp-options,etc.
+#
+
+# we really need to use `expr substr` with dash
+# shellcheck disable=SC2003 disable=SC2308
+
+command -v getarg > /dev/null || . /lib/dracut-lib.sh
+
+if [ -n "$netroot" ] && [ -z "$(getarg ip=)" ] && [ -z "$(getarg BOOTIF=)" ]; then
+ # No ip= argument(s) for netroot provided, defaulting to DHCP
+ return
+fi
+
+# Count ip= lines to decide whether we need bootdev= or not
+if [ -z "$NEEDBOOTDEV" ]; then
+ count=0
+ for p in $(getargs ip=); do
+ case "$p" in
+ ibft)
+ continue
+ ;;
+ esac
+ count=$((count + 1))
+ done
+ [ $count -gt 1 ] && NEEDBOOTDEV=1
+fi
+unset count
+
+# If needed, check if bootdev= contains anything usable
+BOOTDEV=$(getarg bootdev=)
+
+if [ -n "$NEEDBOOTDEV" ] && getargbool 1 rd.neednet; then
+ #[ -z "$BOOTDEV" ] && warn "Please supply bootdev argument for multiple ip= lines"
+ echo "rd.neednet=1" > /etc/cmdline.d/dracut-neednet.conf
+ info "Multiple ip= arguments: assuming rd.neednet=1"
+else
+ unset NEEDBOOTDEV
+fi
+
+# Check ip= lines
+# XXX Would be nice if we could errorcheck ip addresses here as well
+for p in $(getargs ip=); do
+ ip_to_var "$p"
+
+ # make first device specified the BOOTDEV
+ if [ -n "$NEEDBOOTDEV" ] && [ -z "$BOOTDEV" ] && [ -n "$dev" ]; then
+ BOOTDEV="$dev"
+ info "Setting bootdev to '$BOOTDEV'"
+ fi
+
+ # skip ibft since we did it above
+ [ "$autoconf" = "ibft" ] && continue
+
+ # Empty autoconf defaults to 'dhcp'
+ if [ -z "$autoconf" ]; then
+ warn "Empty autoconf values default to dhcp"
+ autoconf="dhcp"
+ fi
+
+ # Error checking for autoconf in combination with other values
+ for autoopt in $(str_replace "$autoconf" "," " "); do
+ case $autoopt in
+ error) die "Error parsing option 'ip=$p'" ;;
+ bootp | rarp | both) die "Sorry, ip=$autoopt is currently unsupported" ;;
+ none | off)
+ [ -z "$ip" ] \
+ && die "For argument 'ip=$p'\nValue '$autoopt' without static configuration does not make sense"
+ [ -z "$mask" ] \
+ && die "Sorry, automatic calculation of netmask is not yet supported"
+ ;;
+ auto6 | link6) ;;
+ either6) ;;
+ dhcp | dhcp6 | on | any | single-dhcp)
+ [ -n "$NEEDBOOTDEV" ] && [ -z "$dev" ] \
+ && die "Sorry, 'ip=$p' does not make sense for multiple interface configurations"
+ [ -n "$ip" ] \
+ && die "For argument 'ip=$p'\nSorry, setting client-ip does not make sense for '$autoopt'"
+ ;;
+ *) die "For argument 'ip=$p'\nSorry, unknown value '$autoopt'" ;;
+ esac
+ done
+
+ if [ -n "$dev" ]; then
+ # We don't like duplicate device configs
+ if [ -n "$IFACES" ]; then
+ for i in $IFACES; do
+ [ "$dev" = "$i" ] && die "For argument 'ip=$p'\nDuplication configurations for '$dev'"
+ done
+ fi
+ # IFACES list for later use
+ IFACES="$IFACES $dev"
+
+ # Interface should exist
+ if [ ! -e "/sys/class/net/$dev" ]; then
+ warn "Network interface '$dev' does not exist"
+ fi
+ fi
+
+ # Do we need to check for specific options?
+ if [ -n "$NEEDDHCP" ] || [ -n "$DHCPORSERVER" ]; then
+ # Correct device? (Empty is ok as well)
+ [ "$dev" = "$BOOTDEV" ] || continue
+ # Server-ip is there?
+ [ -n "$DHCPORSERVER" ] && [ -n "$srv" ] && continue
+ # dhcp? (It's simpler to check for a set ip. Checks above ensure that if
+ # ip is there, we're static
+ [ -z "$ip" ] && continue
+ # Not good!
+ die "Server-ip or dhcp for netboot needed, but current arguments say otherwise"
+ fi
+
+ if str_starts "$dev" "enx" && [ ${#dev} -eq 15 ]; then
+ # shellcheck disable=SC2003
+ printf -- "ifname=%s:%s:%s:%s:%s:%s:%s\n" \
+ "$dev" \
+ "$(expr substr "$dev" 3 2)" \
+ "$(expr substr "$dev" 5 2)" \
+ "$(expr substr "$dev" 7 2)" \
+ "$(expr substr "$dev" 9 2)" \
+ "$(expr substr "$dev" 11 2)" \
+ "$(expr substr "$dev" 13 2)" \
+ >> /etc/cmdline.d/80-enx.conf
+ fi
+done
+
+# put BOOTIF in IFACES to make sure it comes up
+if getargbool 1 "rd.bootif" && BOOTIF="$(getarg BOOTIF=)"; then
+ BOOTDEV=$(fix_bootif "$BOOTIF")
+ IFACES="$BOOTDEV $IFACES"
+fi
+
+# This ensures that BOOTDEV is always first in IFACES
+if [ -n "$BOOTDEV" ] && [ -n "$IFACES" ]; then
+ IFACES="${IFACES%"$BOOTDEV"*} ${IFACES#*"$BOOTDEV"}"
+ IFACES="$BOOTDEV $IFACES"
+fi
+
+# Store BOOTDEV and IFACES for later use
+[ -n "$BOOTDEV" ] && echo "$BOOTDEV" > /tmp/net.bootdev
+[ -n "$IFACES" ] && echo "$IFACES" > /tmp/net.ifaces
diff --git a/modules.d/35network-legacy/parse-team.sh b/modules.d/35network-legacy/parse-team.sh
new file mode 100755
index 0000000..83badc9
--- /dev/null
+++ b/modules.d/35network-legacy/parse-team.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+#
+# Format:
+# team=<teammaster>:<teamslaves>[:<teamrunner>]
+#
+# teamslaves is a comma-separated list of physical (ethernet) interfaces
+# teamrunner is the runner type to be used (see teamd.conf(5)); defaults to activebackup
+#
+# team without parameters assumes team=team0:eth0,eth1:activebackup
+#
+
+parseteam() {
+ local v="${1}":
+ set --
+ while [ -n "$v" ]; do
+ set -- "$@" "${v%%:*}"
+ v=${v#*:}
+ done
+
+ case $# in
+ 0)
+ teammaster=team0
+ teamslaves="eth0 eth1"
+ teamrunner="activebackup"
+ ;;
+ 1)
+ teammaster=$1
+ teamslaves="eth0 eth1"
+ teamrunner="activebackup"
+ ;;
+ 2)
+ teammaster=$1
+ teamslaves=$(str_replace "$2" "," " ")
+ teamrunner="activebackup"
+ ;;
+ 3)
+ teammaster=$1
+ teamslaves=$(str_replace "$2" "," " ")
+ teamrunner=$3
+ ;;
+ *) die "team= requires zero to three parameters" ;;
+ esac
+ return 0
+}
+
+for team in $(getargs team); do
+ [ "$team" = "team" ] && continue
+
+ unset teammaster
+ unset teamslaves
+ unset teamrunner
+
+ parseteam "$team" || continue
+
+ {
+ echo "teammaster=$teammaster"
+ echo "teamslaves=\"$teamslaves\""
+ echo "teamrunner=\"$teamrunner\""
+ } > /tmp/team."${teammaster}".info
+
+ if ! [ -e /etc/teamd/"${teammaster}".conf ]; then
+ warn "Team master $teammaster specified, but no /etc/teamd/$teammaster.conf present. Using $teamrunner."
+ mkdir -p /etc/teamd
+ printf -- "%s" "{\"runner\": {\"name\": \"$teamrunner\"}, \"link_watch\": {\"name\": \"ethtool\"}}" > "/tmp/${teammaster}.conf"
+ fi
+done
diff --git a/modules.d/35network-legacy/parse-vlan.sh b/modules.d/35network-legacy/parse-vlan.sh
new file mode 100755
index 0000000..c23f833
--- /dev/null
+++ b/modules.d/35network-legacy/parse-vlan.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+#
+# Format:
+# vlan=<vlanname>:<phydevice>
+#
+
+parsevlan() {
+ local v="${1}":
+ set --
+ while [ -n "$v" ]; do
+ set -- "$@" "${v%%:*}"
+ v=${v#*:}
+ done
+
+ unset vlanname phydevice
+ case $# in
+ 2)
+ vlanname=$1
+ phydevice=$2
+ ;;
+ *) die "vlan= requires two parameters" ;;
+ esac
+}
+
+for vlan in $(getargs vlan=); do
+ unset vlanname
+ unset phydevice
+ if [ ! "$vlan" = "vlan" ]; then
+ parsevlan "$vlan"
+ fi
+
+ echo "phydevice=\"$phydevice\"" > /tmp/vlan."${phydevice}".phy
+ {
+ echo "vlanname=\"$vlanname\""
+ echo "phydevice=\"$phydevice\""
+ } > /tmp/vlan."${vlanname}"."${phydevice}"
+done
diff --git a/modules.d/35network-manager/initrd-no-auto-default.conf b/modules.d/35network-manager/initrd-no-auto-default.conf
new file mode 100644
index 0000000..8a06e52
--- /dev/null
+++ b/modules.d/35network-manager/initrd-no-auto-default.conf
@@ -0,0 +1,5 @@
+[.config]
+enable=env:initrd
+
+[main]
+no-auto-default=*
diff --git a/modules.d/35network-manager/module-setup.sh b/modules.d/35network-manager/module-setup.sh
new file mode 100755
index 0000000..d9a244a
--- /dev/null
+++ b/modules.d/35network-manager/module-setup.sh
@@ -0,0 +1,84 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ require_binaries sed grep NetworkManager || return 1
+
+ # do not add this module by default
+ return 255
+}
+
+# called by dracut
+depends() {
+ echo dbus bash
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ return 0
+}
+
+# called by dracut
+install() {
+ local _nm_version
+
+ _nm_version=${NM_VERSION:-$(NetworkManager --version)}
+
+ # We don't need `ip` but having it is *really* useful for people debugging
+ # in an emergency shell.
+ inst_multiple ip sed grep
+
+ inst NetworkManager
+ inst_multiple -o /usr/{lib,libexec}/nm-initrd-generator
+ inst_multiple -o /usr/{lib,libexec}/nm-daemon-helper
+ inst_multiple -o teamd dhclient
+ inst_hook cmdline 99 "$moddir/nm-config.sh"
+ if dracut_module_included "systemd"; then
+
+ inst "$dbussystem"/org.freedesktop.NetworkManager.conf
+ inst_multiple nmcli nm-online
+
+ # teaming support under systemd+dbus
+ inst_multiple -o \
+ "$dbussystem"/teamd.conf \
+ "$dbussystemconfdir"/teamd.conf
+
+ # Install a configuration snippet to prevent the automatic creation of
+ # "Wired connection #" DHCP connections for Ethernet interfaces
+ inst_simple "$moddir"/initrd-no-auto-default.conf /usr/lib/NetworkManager/conf.d/
+
+ inst_simple "$moddir"/nm-initrd.service "$systemdsystemunitdir"/nm-initrd.service
+ inst_simple "$moddir"/nm-wait-online-initrd.service "$systemdsystemunitdir"/nm-wait-online-initrd.service
+
+ # Adding default link
+ inst_multiple -o "${systemdnetwork}/99-default.link"
+ [[ $hostonly ]] && inst_multiple -H -o "${systemdnetworkconfdir}/*.link"
+
+ $SYSTEMCTL -q --root "$initdir" enable nm-initrd.service
+ fi
+
+ inst_hook initqueue/settled 99 "$moddir/nm-run.sh"
+
+ inst_rules 85-nm-unmanaged.rules
+ inst_libdir_dir "NetworkManager/$_nm_version"
+ inst_libdir_file "NetworkManager/$_nm_version/libnm-device-plugin-team.so"
+ inst_simple "$moddir/nm-lib.sh" "/lib/nm-lib.sh"
+
+ if [[ -x "$initdir/usr/sbin/dhclient" ]]; then
+ inst_multiple -o /usr/{lib,libexec}/nm-dhcp-helper
+ elif ! [[ -e "$initdir/etc/machine-id" ]]; then
+ # The internal DHCP client silently fails if we
+ # have no machine-id
+ systemd-machine-id-setup --root="$initdir"
+ fi
+
+ # We don't install the ifcfg files from the host automatically.
+ # But the user might choose to include them, so we pull in the machinery to read them.
+ inst_libdir_file "NetworkManager/$_nm_version/libnm-settings-plugin-ifcfg-rh.so"
+
+ _arch=${DRACUT_ARCH:-$(uname -m)}
+
+ inst_libdir_file {"tls/$_arch/",tls/,"$_arch/",}"libnss_dns.so.*" \
+ {"tls/$_arch/",tls/,"$_arch/",}"libnss_mdns4_minimal.so.*"
+}
diff --git a/modules.d/35network-manager/nm-config.sh b/modules.d/35network-manager/nm-config.sh
new file mode 100755
index 0000000..2b13d0a
--- /dev/null
+++ b/modules.d/35network-manager/nm-config.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+type nm_generate_connections > /dev/null 2>&1 || . /lib/nm-lib.sh
+
+if [ -n "$netroot" ] || [ -e /tmp/net.ifaces ]; then
+ echo rd.neednet >> /etc/cmdline.d/35-neednet.conf
+fi
+
+if getargbool 0 rd.debug -d -y rdinitdebug -d -y rdnetdebug; then
+ # shellcheck disable=SC2174
+ mkdir -m 0755 -p /run/NetworkManager/conf.d
+ (
+ echo '[.config]'
+ echo 'enable=env:initrd'
+ echo
+ echo '[logging]'
+ echo 'level=TRACE'
+ ) > /run/NetworkManager/conf.d/initrd-logging.conf
+
+ if [ -n "$DRACUT_SYSTEMD" ]; then
+ # Enable tty output if a usable console is found
+ # See https://github.com/coreos/fedora-coreos-tracker/issues/943
+ # shellcheck disable=SC2217
+ if [ -w /dev/console ] && (echo < /dev/console) > /dev/null 2> /dev/null; then
+ mkdir -p /run/systemd/system/nm-initrd.service.d
+ cat << EOF > /run/systemd/system/nm-initrd.service.d/tty-output.conf
+[Service]
+StandardOutput=tty
+EOF
+ systemctl --no-block daemon-reload
+ fi
+ fi
+fi
+
+nm_generate_connections
diff --git a/modules.d/35network-manager/nm-initrd.service b/modules.d/35network-manager/nm-initrd.service
new file mode 100644
index 0000000..dbd8caa
--- /dev/null
+++ b/modules.d/35network-manager/nm-initrd.service
@@ -0,0 +1,31 @@
+[Unit]
+DefaultDependencies=no
+Wants=systemd-udev-trigger.service
+After=systemd-udev-trigger.service
+After=dracut-cmdline.service
+After=dbus.service
+Wants=network.target
+Before=network.target
+ConditionPathExists=/run/NetworkManager/initrd/neednet
+ConditionPathExistsGlob=|/usr/lib/NetworkManager/system-connections/*
+ConditionPathExistsGlob=|/run/NetworkManager/system-connections/*
+ConditionPathExistsGlob=|/etc/NetworkManager/system-connections/*
+ConditionPathExistsGlob=|/etc/sysconfig/network-scripts/ifcfg-*
+
+[Service]
+Type=dbus
+BusName=org.freedesktop.NetworkManager
+ExecReload=/usr/bin/busctl call org.freedesktop.NetworkManager /org/freedesktop/NetworkManager org.freedesktop.NetworkManager Reload u 0
+ExecStart=/usr/sbin/NetworkManager --debug
+KillMode=process
+# The following gets changed to StandardOutput=tty by nm-config.sh
+# when debug is enabled and a usable console is found.
+StandardOutput=null
+Environment=NM_CONFIG_ENABLE_TAG=initrd
+Restart=on-failure
+ProtectSystem=true
+ProtectHome=read-only
+
+[Install]
+WantedBy=initrd.target
+Also=nm-wait-online-initrd.service
diff --git a/modules.d/35network-manager/nm-lib.sh b/modules.d/35network-manager/nm-lib.sh
new file mode 100755
index 0000000..32a288d
--- /dev/null
+++ b/modules.d/35network-manager/nm-lib.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+type getcmdline > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+nm_generate_connections() {
+ rm -f /run/NetworkManager/system-connections/*
+ if [ -x /usr/libexec/nm-initrd-generator ]; then
+ # shellcheck disable=SC2046
+ /usr/libexec/nm-initrd-generator -- $(getcmdline)
+ elif [ -x /usr/lib/nm-initrd-generator ]; then
+ # shellcheck disable=SC2046
+ /usr/lib/nm-initrd-generator -- $(getcmdline)
+ else
+ warn "nm-initrd-generator not found"
+ fi
+
+ if getargbool 0 rd.neednet; then
+ for i in /usr/lib/NetworkManager/system-connections/* \
+ /run/NetworkManager/system-connections/* \
+ /etc/NetworkManager/system-connections/* \
+ /etc/sysconfig/network-scripts/ifcfg-*; do
+ [ -f "$i" ] || continue
+ mkdir -p "$hookdir"/initqueue/finished
+ echo '[ -f /tmp/nm.done ]' > "$hookdir"/initqueue/finished/nm.sh
+ mkdir -p /run/NetworkManager/initrd
+ : > /run/NetworkManager/initrd/neednet # activate NM services
+ break
+ done
+ fi
+}
+
+nm_reload_connections() {
+ [ -n "$DRACUT_SYSTEMD" ] && systemctl is-active nm-initrd.service && nmcli connection reload
+}
diff --git a/modules.d/35network-manager/nm-run.sh b/modules.d/35network-manager/nm-run.sh
new file mode 100755
index 0000000..14b9cb1
--- /dev/null
+++ b/modules.d/35network-manager/nm-run.sh
@@ -0,0 +1,68 @@
+#!/bin/bash
+
+type source_hook > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+if [ -z "$DRACUT_SYSTEMD" ]; then
+ # Only start NM if networking is needed
+ if [ -e /run/NetworkManager/initrd/neednet ]; then
+ for i in /usr/lib/NetworkManager/system-connections/* \
+ /run/NetworkManager/system-connections/* \
+ /etc/NetworkManager/system-connections/* \
+ /etc/sysconfig/network-scripts/ifcfg-*; do
+ [ -f "$i" ] || continue
+ /usr/sbin/NetworkManager --configure-and-quit=initrd --no-daemon
+ break
+ done
+ fi
+fi
+
+if [ -s /run/NetworkManager/initrd/hostname ]; then
+ cat /run/NetworkManager/initrd/hostname > /proc/sys/kernel/hostname
+fi
+
+kf_get_string() {
+ # NetworkManager writes keyfiles (glib's GKeyFile API). Have a naive
+ # parser for it.
+ #
+ # But GKeyFile will backslash escape certain keys (\s, \t, \n) but also
+ # escape backslash. As an approximation, interpret the string with printf's
+ # '%b'.
+ #
+ # This is supposed to mimic g_key_file_get_string() (poorly).
+
+ v1="$(sed -n "s/^$1=/=/p" | sed '1!d')"
+ test "$v1" = "${v1#=}" && return 1
+ printf "%b" "${v1#=}"
+}
+
+kf_unescape() {
+ # Another layer of unescaping. While values in GKeyFile format
+ # are backslash escaped, the original strings (which are in no
+ # defined encoding) are backslash escaped too to be valid UTF-8.
+ # This will undo the second layer of escaping to give binary "strings".
+ printf "%b" "$1"
+}
+
+kf_parse() {
+ v3="$(kf_get_string "$1")" || return 1
+ v3="$(kf_unescape "$v3")"
+ printf '%s=%s\n' "$2" "$(printf '%q' "$v3")"
+}
+
+dhcpopts_create() {
+ kf_parse root-path new_root_path < "$1"
+ kf_parse next-server new_next_server < "$1"
+ kf_parse dhcp-bootfile filename < "$1"
+}
+
+for _i in /sys/class/net/*; do
+ [ -d "$_i" ] || continue
+ state="/run/NetworkManager/devices/$(cat "$_i"/ifindex)"
+ grep -q '^connection-uuid=' "$state" 2> /dev/null || continue
+ ifname="${_i##*/}"
+ dhcpopts_create "$state" > /tmp/dhclient."$ifname".dhcpopts
+ source_hook initqueue/online "$ifname"
+ /sbin/netroot "$ifname"
+done
+
+: > /tmp/nm.done
diff --git a/modules.d/35network-manager/nm-wait-online-initrd.service b/modules.d/35network-manager/nm-wait-online-initrd.service
new file mode 100644
index 0000000..ac8762a
--- /dev/null
+++ b/modules.d/35network-manager/nm-wait-online-initrd.service
@@ -0,0 +1,16 @@
+[Unit]
+DefaultDependencies=no
+Requires=nm-initrd.service
+After=nm-initrd.service
+Before=network-online.target
+Before=dracut-initqueue.service
+ConditionPathExists=/run/NetworkManager/initrd/neednet
+
+[Service]
+Type=oneshot
+ExecStart=/usr/bin/nm-online -s -q -t 3600
+RemainAfterExit=yes
+
+[Install]
+WantedBy=initrd.target
+WantedBy=network-online.target
diff --git a/modules.d/40network/dhcp-root.sh b/modules.d/40network/dhcp-root.sh
new file mode 100755
index 0000000..3f11221
--- /dev/null
+++ b/modules.d/40network/dhcp-root.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+# This script is sourced, so root should be set. But let's be paranoid
+[ -z "$root" ] && root=$(getarg root=)
+
+if [ -z "$netroot" ]; then
+ for netroot in $(getargs netroot=); do
+ [ "$netroot" = "dhcp" ] && break
+ [ "$netroot" = "dhcp6" ] && break
+ done
+ [ "$netroot" = "dhcp" ] || [ "$netroot" = "dhcp6" ] || unset netroot
+fi
+
+if [ "$root" = "dhcp" ] || [ "$root" = "dhcp6" ] || [ "$netroot" = "dhcp" ] || [ "$netroot" = "dhcp6" ]; then
+ # Tell ip= checker that we need dhcp
+ # shellcheck disable=SC2034
+ NEEDDHCP="1"
+
+ # Done, all good!
+ # shellcheck disable=SC2034
+ rootok=1
+ if [ "$netroot" != "dhcp" ] && [ "$netroot" != "dhcp6" ]; then
+ netroot=$root
+ fi
+
+ # Shut up init error check
+ [ -z "$root" ] && root="dhcp"
+ # shellcheck disable=SC2016
+ echo '[ -d $NEWROOT/proc -o -e /dev/root ]' > "$hookdir"/initqueue/finished/dhcp.sh
+fi
diff --git a/modules.d/40network/ifname-genrules.sh b/modules.d/40network/ifname-genrules.sh
new file mode 100755
index 0000000..b9b95c4
--- /dev/null
+++ b/modules.d/40network/ifname-genrules.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+# if there are no ifname parameters, just use NAME=KERNEL
+if ! getarg ifname= > /dev/null; then
+ return
+fi
+
+command -v parse_ifname_opts > /dev/null || . /lib/net-lib.sh
+
+{
+ for p in $(getargs ifname=); do
+ parse_ifname_opts "$p"
+
+ if [ -f /tmp/ifname-"$ifname_mac" ]; then
+ read -r oldif < /tmp/ifname-"$ifname_mac"
+ fi
+ if [ -f /tmp/ifname-"$ifname_if" ]; then
+ read -r oldmac < /tmp/ifname-"$ifname_if"
+ fi
+ if [ -n "$oldif" -a -n "$oldmac" -a "$oldif" = "$ifname_if" -a "$oldmac" = "$ifname_mac" ]; then
+ # skip same ifname= declaration
+ continue
+ fi
+
+ [ -n "$oldif" ] && warn "Multiple interface names specified for MAC $ifname_mac: $oldif"
+ [ -n "$oldmac" ] && warn "Multiple MAC specified for $ifname_if: $oldmac"
+
+ printf 'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="%s", ATTR{type}=="1", NAME="%s"\n' "$ifname_mac" "$ifname_if"
+ echo "$ifname_if" > /tmp/ifname-"$ifname_mac"
+ echo "$ifname_mac" > /tmp/ifname-"$ifname_if"
+ done
+} >> /etc/udev/rules.d/80-ifname.rules
diff --git a/modules.d/40network/module-setup.sh b/modules.d/40network/module-setup.sh
new file mode 100755
index 0000000..4c77ff3
--- /dev/null
+++ b/modules.d/40network/module-setup.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ return 255
+}
+
+# called by dracut
+depends() {
+ is_qemu_virtualized && echo -n "qemu-net "
+
+ for module in connman network-manager network-legacy systemd-networkd; do
+ if dracut_module_included "$module"; then
+ network_handler="$module"
+ break
+ fi
+ done
+
+ if [ -z "$network_handler" ]; then
+ if check_module "connman"; then
+ network_handler="connman"
+ elif check_module "network-manager"; then
+ network_handler="network-manager"
+ elif check_module "systemd-networkd"; then
+ network_handler="systemd-networkd"
+ else
+ network_handler="network-legacy"
+ fi
+ fi
+ echo "kernel-network-modules $network_handler"
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ return 0
+}
+
+# called by dracut
+install() {
+ inst_script "$moddir/netroot.sh" "/sbin/netroot"
+ inst_simple "$moddir/net-lib.sh" "/lib/net-lib.sh"
+ inst_hook pre-udev 50 "$moddir/ifname-genrules.sh"
+ inst_hook cmdline 91 "$moddir/dhcp-root.sh"
+ inst_multiple ip sed awk grep pgrep tr
+ inst_multiple -o arping arping2
+ dracut_need_initqueue
+}
diff --git a/modules.d/40network/net-lib.sh b/modules.d/40network/net-lib.sh
new file mode 100755
index 0000000..9d88e0d
--- /dev/null
+++ b/modules.d/40network/net-lib.sh
@@ -0,0 +1,906 @@
+#!/bin/sh
+
+# shellcheck disable=SC2034
+IFNETFILE="/tmp/bootnetif"
+
+is_ip() {
+ echo "$1" | {
+ IFS=. read -r a b c d
+ test "$a" -ge 0 -a "$a" -le 255 \
+ -a "$b" -ge 0 -a "$b" -le 255 \
+ -a "$c" -ge 0 -a "$c" -le 255 \
+ -a "$d" -ge 0 -a "$d" -le 255 \
+ 2> /dev/null
+ } && return 0
+ return 1
+}
+
+get_ip() {
+ local iface="$1" ip=""
+ ip=$(ip -f inet addr show "$iface")
+ ip=${ip%%/*}
+ ip=${ip##* }
+ echo "$ip"
+}
+
+iface_for_remote_addr() {
+ # shellcheck disable=SC2046
+ set -- $(ip route get to "$@" | sed 's/.*\bdev\b//p;q')
+ echo "$1"
+}
+
+iface_for_ip() {
+ # shellcheck disable=SC2046
+ set -- $(ip addr show to "$@")
+ echo "${2%:}"
+}
+
+iface_for_mac() {
+ local interface=""
+ local mac
+ mac="$(echo "$@" | sed 'y/ABCDEF/abcdef/')"
+ for interface in /sys/class/net/*; do
+ if [ "$(cat "$interface"/address)" = "$mac" ]; then
+ echo "${interface##*/}"
+ fi
+ done
+}
+
+# get the iface name for the given identifier - either a MAC, IP, or iface name
+iface_name() {
+ case "$1" in
+ ??:??:??:??:??:?? | ??-??-??-??-??-??) iface_for_mac "$1" ;;
+ *:*:* | *.*.*.*) iface_for_ip "$1" ;;
+ *) echo "$1" ;;
+ esac
+}
+
+# list the configured interfaces
+configured_ifaces() {
+ local IFACES="" iface_id="" rv=1
+ [ -e "/tmp/net.ifaces" ] && read -r IFACES < /tmp/net.ifaces
+ if { pidof udevd || pidof systemd-udevd; } > /dev/null; then
+ for iface_id in $IFACES; do
+ printf "%s\n" "$(iface_name "$iface_id")"
+ rv=0
+ done
+ else
+ warn "configured_ifaces called before udev is running"
+ echo "$IFACES"
+ [ -n "$IFACES" ] && rv=0
+ fi
+ return $rv
+}
+
+all_ifaces_up() {
+ local iface="" IFACES=""
+ [ -e "/tmp/net.ifaces" ] && read -r IFACES < /tmp/net.ifaces
+ for iface in $IFACES; do
+ [ -e /tmp/net."$iface".up ] || return 1
+ done
+}
+
+all_ifaces_setup() {
+ local iface="" IFACES=""
+ [ -e "/tmp/net.ifaces" ] && read -r IFACES < /tmp/net.ifaces
+ for iface in $IFACES; do
+ [ -e /tmp/net."$iface".did-setup ] || return 1
+ done
+}
+
+get_netroot_ip() {
+ local prefix="" server="" rest=""
+ splitsep ":" "$1" prefix server rest
+ case $server in
+ [0-9]*\.[0-9]*\.[0-9]*\.[0-9]*)
+ echo "$server"
+ return 0
+ ;;
+ esac
+ return 1
+}
+
+ip_is_local() {
+ li=$(ip route get "$@" 2> /dev/null)
+ if [ -n "$li" ]; then
+ strstr "$li" " via " || return 0
+ fi
+ return 1
+}
+
+ifdown() {
+ local netif="$1"
+ # ip down/flush ensures that routing info goes away as well
+ ip link set "$netif" down
+ ip addr flush dev "$netif"
+ echo "#empty" > /etc/resolv.conf
+ rm -f -- /tmp/net."$netif".did-setup
+ [ -z "$DO_VLAN" ] \
+ && [ -e /sys/class/net/"$netif"/address ] \
+ && rm -f -- "/tmp/net.$(cat /sys/class/net/"$netif"/address).did-setup"
+ # TODO: send "offline" uevent?
+}
+
+setup_net() {
+ local netif="$1" f="" gw_ip="" netroot_ip="" iface="" IFACES=""
+ local _p
+ [ -e /tmp/net."$netif".did-setup ] && return
+ [ -z "$DO_VLAN" ] \
+ && [ -e /sys/class/net/"$netif"/address ] \
+ && [ -e "/tmp/net.$(cat /sys/class/net/"$netif"/address).did-setup" ] && return
+ [ -e "/tmp/net.ifaces" ] && read -r IFACES < /tmp/net.ifaces
+ [ -z "$IFACES" ] && IFACES="$netif"
+ # run the scripts written by ifup
+ # shellcheck disable=SC1090
+ [ -e /tmp/net."$netif".hostname ] && . /tmp/net."$netif".hostname
+ # shellcheck disable=SC1090
+ [ -e /tmp/net."$netif".override ] && . /tmp/net."$netif".override
+ # shellcheck disable=SC1090
+ [ -e /tmp/dhclient."$netif".dhcpopts ] && . /tmp/dhclient."$netif".dhcpopts
+ # set up resolv.conf
+ [ -e /tmp/net."$netif".resolv.conf ] \
+ && awk '!array[$0]++' /tmp/net."$netif".resolv.conf > /etc/resolv.conf
+ # shellcheck disable=SC1090
+ [ -e /tmp/net."$netif".gw ] && . /tmp/net."$netif".gw
+
+ # add static route
+ for _p in $(getargs rd.route); do
+ route_to_var "$_p" || continue
+ [ -n "$route_dev" ] && [ "$route_dev" != "$netif" ] && continue
+ ip route add "$route_mask" ${route_gw:+via $route_gw} ${route_dev:+dev $route_dev}
+ if strstr "$route_mask" ":"; then
+ printf -- "%s\n" "$route_mask ${route_gw:+via $route_gw} ${route_dev:+dev $route_dev}" \
+ > /tmp/net.route6."$netif"
+ else
+ printf -- "%s\n" "$route_mask ${route_gw:+via $route_gw} ${route_dev:+dev $route_dev}" \
+ > /tmp/net.route."$netif"
+ fi
+ done
+
+ # If a static route was necessary to reach the gateway, the
+ # first gateway setup call will have failed with
+ # RTNETLINK answers: Network is unreachable
+ # Replace the default route again after static routes to cover
+ # this scenario.
+ # shellcheck disable=SC1090
+ [ -e /tmp/net."$netif".gw ] && . /tmp/net."$netif".gw
+
+ # Handle STP Timeout: arping the default gateway.
+ # (or the root server, if a) it's local or b) there's no gateway.)
+ # Note: This assumes that if no router is present the
+ # root server is on the same subnet.
+
+ # Get DHCP-provided router IP, or the cmdline-provided "gw=" argument
+ [ -n "$new_routers" ] && gw_ip=${new_routers%%,*}
+ [ -n "$gw" ] && gw_ip=$gw
+
+ # Get the "netroot" IP (if there's an IP address in there)
+ netroot_ip=$(get_netroot_ip "$netroot")
+
+ # try netroot if it's local (or there's no gateway)
+ if ip_is_local "$netroot_ip" || [ -z "$gw_ip" ]; then
+ dest="$netroot_ip"
+ else
+ dest="$gw_ip"
+ fi
+
+ unset layer2
+ if [ -f /sys/class/net/"$netif"/device/layer2 ]; then
+ read -r layer2 < /sys/class/net/"$netif"/device/layer2
+ fi
+
+ if [ "$layer2" != "0" ] && [ -n "$dest" ] && ! strstr "$dest" ":"; then
+ if command -v arping2 > /dev/null; then
+ arping2 -q -C 1 -c 60 -I "$netif" "$dest" || info "Resolving $dest via ARP on $netif failed"
+ else
+ arping -q -f -w 60 -I "$netif" "$dest" || info "Resolving $dest via ARP on $netif failed"
+ fi
+ fi
+ unset layer2
+
+ : > /tmp/net."$netif".did-setup
+ [ -z "$DO_VLAN" ] \
+ && [ -e /sys/class/net/"$netif"/address ] \
+ && : > "/tmp/net.$(cat /sys/class/net/"$netif"/address).did-setup"
+}
+
+save_netinfo() {
+ local netif="$1" IFACES="" f="" i=""
+ [ -e /tmp/net.ifaces ] && read -r IFACES < /tmp/net.ifaces
+ # Add $netif to the front of IFACES (if it's not there already).
+ set -- "$netif"
+ for i in $IFACES; do [ "$i" != "$netif" ] && set -- "$@" "$i"; done
+ IFACES="$*"
+ for i in $IFACES; do
+ for f in "/tmp/dhclient.$i."*; do
+ [ -f "$f" ] && cp -f "$f" /tmp/net."${f#/tmp/dhclient.}"
+ done
+ done
+ echo "$IFACES" > /tmp/.net.ifaces.new
+ mv /tmp/.net.ifaces.new /tmp/net.ifaces
+}
+
+set_ifname() {
+ local name="$1" mac="$2" num=-1 n=""
+ # if it's already set, return the existing name
+ for n in $(getargs ifname=); do
+ strstr "$n" "$mac" && echo "${n%%:*}" && return
+ done
+ [ ! -f "/tmp/set_ifname_$name" ] || read -r num < "/tmp/set_ifname_$name"
+ # otherwise, pick a new name and use that
+ while :; do
+ num=$((num + 1))
+ [ -e /sys/class/net/"$name"$num ] && continue
+ for n in $(getargs ifname=); do
+ [ "$name$num" = "${n%%:*}" ] && continue 2
+ done
+ break
+ done
+ echo "ifname=$name$num:$mac" >> /etc/cmdline.d/45-ifname.conf
+ echo "$num" > "/tmp/set_ifname_$name"
+ echo "$name$num"
+}
+
+# pxelinux provides macaddr '-' separated, but we need ':'
+fix_bootif() {
+ local macaddr="${1}"
+ local IFS='-'
+ # shellcheck disable=SC2086
+ macaddr=$(printf '%s:' ${macaddr})
+ macaddr=${macaddr%:}
+ # strip hardware type field from pxelinux
+ [ -n "${macaddr%??:??:??:??:??:??}" ] && macaddr=${macaddr#??:}
+ # return macaddr with lowercase alpha characters expected by udev
+ echo "$macaddr" | sed 'y/ABCDEF/abcdef/'
+}
+
+ibft_to_cmdline() {
+ local iface=""
+ modprobe -q iscsi_ibft
+ (
+ for iface in /sys/firmware/ibft/ethernet*; do
+ local mac="" dev=""
+ local dhcp="" ip="" gw="" mask="" hostname=""
+ local dns1 dns2
+
+ [ -e "${iface}"/mac ] || continue
+ read -r mac < "${iface}"/mac
+ [ -z "$mac" ] && continue
+ dev=$(set_ifname ibft "$mac")
+
+ [ -e /tmp/net."${dev}".has_ibft_config ] && continue
+
+ [ -e "${iface}"/flags ] && read -r flags < "${iface}"/flags
+ # Skip invalid interfaces
+ awk -- 'BEGIN { exit (!and('"$flags"',1)) }' || continue
+ # Skip interfaces not used for booting unless using multipath
+ if ! getargbool 0 rd.iscsi.mp; then
+ awk -- 'BEGIN { exit (!and('"$flags"',2)) }' || continue
+ fi
+ [ -e "${iface}"/dhcp ] && read -r dhcp < "${iface}"/dhcp
+ [ -e "${iface}"/origin ] && read -r origin < "${iface}"/origin
+ [ -e "${iface}"/ip-addr ] && read -r ip < "${iface}"/ip-addr
+
+ if [ -n "$ip" ]; then
+ case "$ip" in
+ *.*.*.*)
+ family=ipv4
+ ;;
+ *:*)
+ family=ipv6
+ ;;
+ esac
+ fi
+ if [ -n "$dhcp" ] || [ "$origin" -eq 3 ]; then
+ if [ "$family" = "ipv6" ]; then
+ echo "ip=$dev:dhcp6"
+ else
+ echo "ip=$dev:dhcp"
+ fi
+ elif [ -e "${iface}"/ip-addr ]; then
+ # skip not assigned ip addresses
+ [ "$ip" = "0.0.0.0" ] && continue
+ [ -e "${iface}"/gateway ] && read -r gw < "${iface}"/gateway
+ [ "$gw" = "0.0.0.0" ] && unset gw
+ [ -e "${iface}"/subnet-mask ] && read -r mask < "${iface}"/subnet-mask
+ [ -e "${iface}"/prefix-len ] && read -r prefix < "${iface}"/prefix-len
+ [ -e "${iface}"/primary-dns ] && read -r dns1 < "${iface}"/primary-dns
+ [ "$dns1" = "0.0.0.0" ] && unset dns1
+ [ -e "${iface}"/secondary-dns ] && read -r dns2 < "${iface}"/secondary-dns
+ [ "$dns2" = "0.0.0.0" ] && unset dns
+ [ -e "${iface}"/hostname ] && read -r hostname < "${iface}"/hostname
+ if [ "$family" = "ipv6" ]; then
+ if [ -n "$ip" ]; then
+ [ -n "$prefix" ] || prefix=128
+ ip="[${ip}]"
+ mask=$prefix
+ fi
+ if [ -n "$gw" ]; then
+ gw="[${gw}]"
+ fi
+ fi
+ if [ -n "$ip" ] && [ -n "$mask" -o -n "$prefix" ]; then
+ echo "ip=$ip::$gw:$mask:$hostname:$dev:none${dns1:+:$dns1}${dns2:+:$dns2}"
+ else
+ warn "${iface} does not contain a valid iBFT configuration"
+ warn "ip-addr=$ip"
+ warn "gateway=$gw"
+ warn "subnet-mask=$mask"
+ warn "hostname=$hostname"
+ fi
+ else
+ info "${iface} does not contain a valid iBFT configuration"
+ # shellcheck disable=SC2012
+ ls -l "${iface}" | vinfo
+ fi
+
+ if [ -e "${iface}"/vlan ]; then
+ read -r vlan < "${iface}"/vlan
+ if [ "$vlan" -ne "0" ]; then
+ case "$vlan" in
+ [0-9]*)
+ echo "vlan=$dev.$vlan:$dev"
+ echo "$mac" > /tmp/net."${dev}"."${vlan}".has_ibft_config
+ ;;
+ *)
+ echo "vlan=$vlan:$dev"
+ echo "$mac" > /tmp/net."${vlan}".has_ibft_config
+ ;;
+ esac
+ else
+ echo "$mac" > /tmp/net."${dev}".has_ibft_config
+ fi
+ else
+ echo "$mac" > /tmp/net."${dev}".has_ibft_config
+ fi
+
+ done
+ ) >> /etc/cmdline.d/40-ibft.conf
+}
+
+parse_iscsi_root() {
+ local v
+ v=${1#iscsi:}
+
+ # extract authentication info
+ case "$v" in
+ *@*:*:*:*:*)
+ authinfo=${v%%@*}
+ v=${v#*@}
+ # allow empty authinfo to allow having an @ in iscsi_target_name like this:
+ # netroot=iscsi:@192.168.1.100::3260::iqn.2009-01.com.example:testdi@sk
+ if [ -n "$authinfo" ]; then
+ OLDIFS="$IFS"
+ IFS=:
+ # shellcheck disable=SC2086
+ set $authinfo
+ IFS="$OLDIFS"
+ if [ $# -gt 4 ]; then
+ warn "Wrong authentication info in iscsi: parameter!"
+ return 1
+ fi
+ iscsi_username=$1
+ iscsi_password=$2
+ if [ $# -gt 2 ]; then
+ iscsi_in_username=$3
+ iscsi_in_password=$4
+ fi
+ fi
+ ;;
+ esac
+
+ # extract target ip
+ case "$v" in
+ [[]*[]]:*)
+ iscsi_target_ip=${v#[[]}
+ iscsi_target_ip=${iscsi_target_ip%%[]]*}
+ v=${v#[[]"$iscsi_target_ip"[]]:}
+ ;;
+ *)
+ iscsi_target_ip=${v%%[:]*}
+ v=${v#"$iscsi_target_ip":}
+ ;;
+ esac
+
+ unset iscsi_target_name
+ # extract target name
+ case "$v" in
+ *:iqn.*)
+ iscsi_target_name=iqn.${v##*:iqn.}
+ v=${v%:iqn.*}:
+ ;;
+ *:eui.*)
+ iscsi_target_name=eui.${v##*:eui.}
+ v=${v%:eui.*}:
+ ;;
+ *:naa.*)
+ iscsi_target_name=naa.${v##*:naa.}
+ v=${v%:naa.*}:
+ ;;
+ esac
+
+ # parse the rest
+ OLDIFS="$IFS"
+ IFS=:
+ # shellcheck disable=SC2086
+ set $v
+ IFS="$OLDIFS"
+
+ iscsi_protocol=$1
+ shift # ignored
+ iscsi_target_port=$1
+ shift
+
+ if [ -n "$iscsi_target_name" ]; then
+ if [ $# -eq 3 ]; then
+ iscsi_iface_name=$1
+ shift
+ fi
+ if [ $# -eq 2 ]; then
+ iscsi_netdev_name=$1
+ shift
+ fi
+ iscsi_lun=$1
+ shift
+ if [ $# -ne 0 ]; then
+ warn "Invalid parameter in iscsi: parameter!"
+ return 1
+ fi
+ return 0
+ fi
+
+ if [ $# -gt 3 ] && [ -n "$1$2" ]; then
+ if [ -z "$3" ] || [ "$3" -ge 0 ] 2> /dev/null; then
+ iscsi_iface_name=$1
+ shift
+ iscsi_netdev_name=$1
+ shift
+ fi
+ fi
+
+ iscsi_lun=$1
+ shift
+
+ iscsi_target_name=$(printf "%s:" "$@")
+ iscsi_target_name=${iscsi_target_name%:}
+}
+
+ip_to_var() {
+ local v="${1}":
+ local i
+ set --
+ while [ -n "$v" ]; do
+ if [ "${v#\[*:*:*\]:}" != "$v" ]; then
+ # handle IPv6 address
+ i="${v%%\]:*}"
+ i="${i##\[}"
+ set -- "$@" "$i"
+ v=${v#\["$i"\]:}
+ else
+ set -- "$@" "${v%%:*}"
+ v=${v#*:}
+ fi
+ done
+
+ unset ip srv gw mask hostname dev autoconf macaddr mtu dns1 dns2
+
+ if [ $# -eq 0 ]; then
+ autoconf="error"
+ return 0
+ fi
+
+ if [ $# -eq 1 ]; then
+ # format: ip={dhcp|on|any|dhcp6|auto6|either6|single-dhcp}
+ # or
+ # ip=<ipv4-address> means anaconda-style static config argument cluster
+ autoconf="$1"
+
+ if strglob "$autoconf" "*.*.*.*"; then
+ # ip=<ipv4-address> means anaconda-style static config argument cluster:
+ # ip=<ip> gateway=<gw> netmask=<nm> hostname=<host> mtu=<mtu>
+ # ksdevice={link|bootif|ibft|<MAC>|<ifname>}
+ ip="$autoconf"
+ gw=$(getarg gateway=)
+ mask=$(getarg netmask=)
+ hostname=$(getarg hostname=)
+ dev=$(getarg ksdevice=)
+ autoconf="none"
+ mtu=$(getarg mtu=)
+
+ # handle special values for ksdevice
+ case "$dev" in
+ bootif | BOOTIF) dev=$(fix_bootif "$(getarg BOOTIF=)") ;;
+ link) dev="" ;; # FIXME: do something useful with this
+ ibft) dev="" ;; # ignore - ibft is handled elsewhere
+ esac
+ fi
+ return 0
+ fi
+
+ if [ "$2" = "dhcp" -o "$2" = "on" -o "$2" = "any" -o "$2" = "dhcp6" -o "$2" = "auto6" -o "$2" = "either6" ]; then
+ # format: ip=<interface>:{dhcp|on|any|dhcp6|auto6}[:[<mtu>][:<macaddr>]]
+ [ -n "$1" ] && dev="$1"
+ [ -n "$2" ] && autoconf="$2"
+ [ -n "$3" ] && mtu=$3
+ if [ -z "$5" ]; then
+ macaddr="$4"
+ else
+ macaddr="${4}:${5}:${6}:${7}:${8}:${9}"
+ fi
+ return 0
+ fi
+
+ # format: ip=<client-IP>:[<peer>]:<gateway-IP>:<netmask>:<client_hostname>:<interface>:{none|off|dhcp|on|any|dhcp6|auto6|ibft}:[:[<mtu>][:<macaddr>]]
+
+ [ -n "$1" ] && ip=$1
+ [ -n "$2" ] && srv=$2
+ [ -n "$3" ] && gw=$3
+ [ -n "$4" ] && mask=$4
+ [ -n "$5" ] && hostname=$5
+ [ -n "$6" ] && dev=$6
+ [ -n "$7" ] && autoconf=$7
+ case "$8" in
+ [0-9a-fA-F]*:* | [0-9]*.[0-9]*.[0-9]*.[0-9]*)
+ dns1="$8"
+ [ -n "$9" ] && dns2="$9"
+ ;;
+ [0-9]*)
+ mtu="$8"
+ if [ -n "${9}" -a -z "${10}" ]; then
+ macaddr="${9}"
+ elif [ -n "${9}" -a -n "${10}" -a -n "${11}" -a -n "${12}" -a -n "${13}" -a -n "${14}" ]; then
+ macaddr="${9}:${10}:${11}:${12}:${13}:${14}"
+ fi
+ ;;
+ *)
+ if [ -n "${9}" -a -z "${10}" ]; then
+ macaddr="${9}"
+ elif [ -n "${9}" -a -n "${10}" -a -n "${11}" -a -n "${12}" -a -n "${13}" -a -n "${14}" ]; then
+ macaddr="${9}:${10}:${11}:${12}:${13}:${14}"
+ fi
+ ;;
+ esac
+ return 0
+}
+
+route_to_var() {
+ local v="${1}":
+ local i
+ set --
+ while [ -n "$v" ]; do
+ if [ "${v#\[*:*:*\]:}" != "$v" ]; then
+ # handle IPv6 address
+ i="${v%%\]:*}"
+ i="${i##\[}"
+ set -- "$@" "$i"
+ v=${v#\["$i"\]:}
+ else
+ set -- "$@" "${v%%:*}"
+ v=${v#*:}
+ fi
+ done
+
+ unset route_mask route_gw route_dev
+ case $# in
+ 2)
+ [ -n "$1" ] && route_mask="$1"
+ [ -n "$2" ] && route_gw="$2"
+ return 0
+ ;;
+ 3)
+ [ -n "$1" ] && route_mask="$1"
+ [ -n "$2" ] && route_gw="$2"
+ [ -n "$3" ] && route_dev="$3"
+ return 0
+ ;;
+ *) return 1 ;;
+ esac
+}
+
+parse_ifname_opts() {
+ local IFS=:
+ # shellcheck disable=SC2086
+ set -- $1
+
+ case $# in
+ 7)
+ ifname_if=$1
+ # udev requires MAC addresses to be lower case
+ ifname_mac=$(echo "$2:$3:$4:$5:$6:$7" | sed 'y/ABCDEF/abcdef/')
+ ;;
+ 21)
+ ifname_if=$1
+ # udev requires MAC addresses to be lower case
+ ifname_mac=$(echo "$2:$3:$4:$5:$6:$7:$8:$9:${10}:${11}:${12}:${13}:${14}:${15}:${16}:${17}:${18}:${19}:${20}:${21}" | sed 'y/ABCDEF/abcdef/')
+ ;;
+ *)
+ die "Invalid arguments for ifname="
+ ;;
+ esac
+
+ case $ifname_if in
+ eth[0-9] | eth[0-9][0-9] | eth[0-9][0-9][0-9] | eth[0-9][0-9][0-9][0-9])
+ warn "ifname=$ifname_if uses the kernel name space for interfaces"
+ warn "This can fail for multiple network interfaces and is discouraged!"
+ warn 'Please use a custom name like "netboot" or "bluesocket"'
+ warn "or use biosdevname and no ifname= at all."
+ ;;
+ esac
+
+}
+
+# some network driver need long time to initialize, wait before it's ready.
+wait_for_if_link() {
+ local cnt=0
+ local li
+ local timeout
+ timeout=$(getargs rd.net.timeout.iflink=)
+ timeout=${timeout:-60}
+ timeout=$((timeout * 10))
+
+ while [ $cnt -lt $timeout ]; do
+ li=$(ip link show dev "$@" 2> /dev/null)
+ [ -n "$li" ] && return 0
+ sleep 0.1
+ cnt=$((cnt + 1))
+ done
+ return 1
+}
+
+wait_for_if_up() {
+ local cnt=0
+ local li
+ local timeout
+ timeout=$(getargs rd.net.timeout.ifup=)
+ timeout=${timeout:-20}
+ timeout=$((timeout * 10))
+
+ while [ $cnt -lt $timeout ]; do
+ li=$(ip link show up dev "$@")
+ if [ -n "$li" ]; then
+ case "$li" in
+ *\<UP*)
+ return 0
+ ;;
+ *\<*,UP\>*)
+ return 0
+ ;;
+ *\<*,UP,*\>*)
+ return 0
+ ;;
+ esac
+ fi
+ if strstr "$li" "LOWER_UP" \
+ && strstr "$li" "state UNKNOWN" \
+ && ! strstr "$li" "DORMANT"; then
+ return 0
+ fi
+ sleep 0.1
+ cnt=$((cnt + 1))
+ done
+ return 1
+}
+
+wait_for_route_ok() {
+ local cnt=0
+ local timeout
+ timeout=$(getargs rd.net.timeout.route=)
+ timeout=${timeout:-20}
+ timeout=$((timeout * 10))
+
+ while [ $cnt -lt $timeout ]; do
+ li=$(ip route show)
+ [ -n "$li" ] && [ -z "${li##*"$1"*}" ] && return 0
+ sleep 0.1
+ cnt=$((cnt + 1))
+ done
+ return 1
+}
+
+wait_for_ipv6_dad_link() {
+ local cnt=0
+ local timeout
+ timeout=$(getargs rd.net.timeout.ipv6dad=)
+ timeout=${timeout:-50}
+ timeout=$((timeout * 10))
+
+ while [ $cnt -lt $timeout ]; do
+ [ -n "$(ip -6 addr show dev "$@" scope link)" ] \
+ && [ -z "$(ip -6 addr show dev "$@" scope link tentative)" ] \
+ && return 0
+ [ -n "$(ip -6 addr show dev "$@" scope link dadfailed)" ] \
+ && return 1
+ sleep 0.1
+ cnt=$((cnt + 1))
+ done
+ return 1
+}
+
+wait_for_ipv6_dad() {
+ local cnt=0
+ local timeout
+ timeout=$(getargs rd.net.timeout.ipv6dad=)
+ timeout=${timeout:-50}
+ timeout=$((timeout * 10))
+
+ while [ $cnt -lt $timeout ]; do
+ [ -n "$(ip -6 addr show dev "$@")" ] \
+ && [ -z "$(ip -6 addr show dev "$@" tentative)" ] \
+ && return 0
+ [ -n "$(ip -6 addr show dev "$@" dadfailed)" ] \
+ && return 1
+ sleep 0.1
+ cnt=$((cnt + 1))
+ done
+ return 1
+}
+
+wait_for_ipv6_auto() {
+ local cnt=0
+ local timeout
+ timeout=$(getargs rd.net.timeout.ipv6auto=)
+ timeout=${timeout:-40}
+ timeout=$((timeout * 10))
+
+ while [ $cnt -lt $timeout ]; do
+ [ -z "$(ip -6 addr show dev "$@" tentative)" ] \
+ && { ip -6 route list proto ra dev "$@" | grep -q ^default; } \
+ && return 0
+ sleep 0.1
+ cnt=$((cnt + 1))
+ done
+ return 1
+}
+
+linkup() {
+ wait_for_if_link "$@" 2> /dev/null && ip link set "$@" up 2> /dev/null && wait_for_if_up "$@" 2> /dev/null
+}
+
+type hostname > /dev/null 2>&1 \
+ || hostname() {
+ cat /proc/sys/kernel/hostname
+ }
+
+iface_has_carrier() {
+ local cnt=0
+ local iface="$1" flags=""
+ local timeout
+ local iface_sys_path
+ [ -n "$iface" ] || return 2
+ iface_sys_path="/sys/class/net/$iface"
+ [ -d "$iface_sys_path" ] || return 2
+ timeout=$(getargs rd.net.timeout.carrier=)
+ timeout=${timeout:-10}
+ timeout=$((timeout * 10))
+
+ linkup "$1"
+
+ li=$(ip link show up dev "$iface")
+ strstr "$li" "NO-CARRIER" && _no_carrier_flag=1
+
+ while [ $cnt -lt $timeout ]; do
+ if [ -n "$_no_carrier_flag" ]; then
+ li=$(ip link show up dev "$iface")
+ # NO-CARRIER flag was cleared
+ strstr "$li" "NO-CARRIER" || return 0
+ elif ! [ -e "$iface_sys_path/carrier" ]; then
+ # sysfs not available and "NO-CARRIER" not displayed
+ return 0
+ fi
+ # double check the syscfs carrier flag
+ [ -e "$iface_sys_path/carrier" ] && [ "$(cat "$iface_sys_path"/carrier)" = 1 ] && return 0
+ sleep 0.1
+ cnt=$((cnt + 1))
+ done
+ return 1
+}
+
+iface_has_link() {
+ iface_has_carrier "$@"
+}
+
+iface_is_enslaved() {
+ local _li
+ _li=$(ip link show dev "$@")
+ strstr "$_li" " master " || return 1
+ return 0
+}
+
+find_iface_with_link() {
+ local iface_path="" iface=""
+ for iface_path in /sys/class/net/*; do
+ iface=${iface_path##*/}
+ str_starts "$iface" "lo" && continue
+ if iface_has_link "$iface"; then
+ echo "$iface"
+ return 0
+ fi
+ done
+ return 1
+}
+
+is_persistent_ethernet_name() {
+ local _netif="$1"
+ local _name_assign_type="0"
+
+ [ -f "/sys/class/net/$_netif/name_assign_type" ] \
+ && read -r _name_assign_type < "/sys/class/net/$_netif/name_assign_type" 2> /dev/null
+
+ # NET_NAME_ENUM 1
+ [ "$_name_assign_type" = "1" ] && return 1
+
+ # NET_NAME_PREDICTABLE 2
+ [ "$_name_assign_type" = "2" ] && return 0
+
+ case "$_netif" in
+ # udev persistent interface names
+ eno[0-9] | eno[0-9][0-9] | eno[0-9][0-9][0-9]*) ;;
+
+ ens[0-9] | ens[0-9][0-9] | ens[0-9][0-9][0-9]*) ;;
+
+ enp[0-9]s[0-9]* | enp[0-9][0-9]s[0-9]* | enp[0-9][0-9][0-9]*s[0-9]*) ;;
+
+ enP*p[0-9]s[0-9]* | enP*p[0-9][0-9]s[0-9]* | enP*p[0-9][0-9][0-9]*s[0-9]*) ;;
+
+ # biosdevname
+ em[0-9] | em[0-9][0-9] | em[0-9][0-9][0-9]*) ;;
+
+ p[0-9]p[0-9]* | p[0-9][0-9]p[0-9]* | p[0-9][0-9][0-9]*p[0-9]*) ;;
+
+ *)
+ return 1
+ ;;
+ esac
+ return 0
+}
+
+is_kernel_ethernet_name() {
+ local _netif="$1"
+ local _name_assign_type="1"
+
+ if [ -e "/sys/class/net/$_netif/name_assign_type" ]; then
+ read -r _name_assign_type < "/sys/class/net/$_netif/name_assign_type"
+
+ case "$_name_assign_type" in
+ 2 | 3 | 4)
+ # NET_NAME_PREDICTABLE 2
+ # NET_NAME_USER 3
+ # NET_NAME_RENAMED 4
+ return 1
+ ;;
+ 1 | *)
+ # NET_NAME_ENUM 1
+ return 0
+ ;;
+ esac
+ fi
+
+ # fallback to error prone manual name check
+ case "$_netif" in
+ eth[0-9] | eth[0-9][0-9] | eth[0-9][0-9][0-9]*)
+ return 0
+ ;;
+ *)
+ return 1
+ ;;
+ esac
+
+}
+
+iface_get_subchannels() {
+ local _netif
+ local _subchannels
+
+ _netif="$1"
+
+ _subchannels=$({
+ for i in /sys/class/net/"$_netif"/device/cdev[0-9]*; do
+ [ -e "$i" ] || continue
+ channel=$(readlink -f "$i")
+ printf -- "%s" "${channel##*/},"
+ done
+ })
+ [ -n "$_subchannels" ] || return 1
+
+ printf -- "%s" "${_subchannels%,}"
+}
diff --git a/modules.d/40network/netroot.sh b/modules.d/40network/netroot.sh
new file mode 100755
index 0000000..8f97774
--- /dev/null
+++ b/modules.d/40network/netroot.sh
@@ -0,0 +1,92 @@
+#!/bin/sh
+
+PATH=/usr/sbin:/usr/bin:/sbin:/bin
+command -v getarg > /dev/null || . /lib/dracut-lib.sh
+command -v setup_net > /dev/null || . /lib/net-lib.sh
+
+# Huh? Empty $1?
+[ -z "$1" ] && exit 1
+
+# [ ! -z $2 ] means this is for manually bringing up network
+# instead of real netroot; If It's called without $2, then there's
+# no sense in doing something if no (net)root info is available
+# or root is already there
+[ -d "$NEWROOT"/proc ] && exit 0
+
+if [ -z "$netroot" ]; then
+ netroot=$(getarg netroot=)
+fi
+
+[ -z "$netroot" ] && exit 1
+
+# Set or override primary interface
+netif=$1
+[ -e "/tmp/net.bootdev" ] && read -r netif < /tmp/net.bootdev
+
+case "$netif" in
+ ??:??:??:??:??:??) # MAC address
+ for i in /sys/class/net/*/address; do
+ read -r mac < "$i"
+ if [ "$mac" = "$netif" ]; then
+ i=${i%/address}
+ netif=${i##*/}
+ break
+ fi
+ done ;;
+esac
+
+# Figure out the handler for root=dhcp by recalling all netroot cmdline
+# handlers when this is not called from manually network bringing up.
+if [ -z "$2" ]; then
+ if getarg "root=dhcp" || getarg "netroot=dhcp" || getarg "root=dhcp6" || getarg "netroot=dhcp6"; then
+ # Load dhcp options
+ # shellcheck disable=SC1090
+ [ -e /tmp/dhclient."$netif".dhcpopts ] && . /tmp/dhclient."$netif".dhcpopts
+
+ # If we have a specific bootdev with no dhcpoptions or empty root-path,
+ # we die. Otherwise we just warn
+ if [ -z "$new_root_path" ]; then
+ [ -n "$BOOTDEV" ] && die "No dhcp root-path received for '$BOOTDEV'"
+ warn "No dhcp root-path received for '$netif' trying other interfaces if available"
+ exit 1
+ fi
+
+ rm -f -- "$hookdir"/initqueue/finished/dhcp.sh
+
+ # Set netroot to new_root_path, so cmdline parsers don't call
+ netroot=$new_root_path
+
+ # FIXME!
+ unset rootok
+ for f in "$hookdir"/cmdline/90*.sh; do
+ # shellcheck disable=SC1090
+ [ -f "$f" ] && . "$f"
+ done
+ else
+ rootok="1"
+ fi
+
+ # Check: do we really know how to handle (net)root?
+ if [ -z "$root" ]; then
+ root=$(getarg root=)
+ fi
+ [ -z "$root" ] && die "No or empty root= argument"
+ [ -z "$rootok" ] && die "Don't know how to handle 'root=$root'"
+
+ handler=${netroot%%:*}
+ handler=${handler%%4}
+ handler=$(command -v "${handler}"root)
+ if [ -z "$netroot" ] || [ ! -e "$handler" ]; then
+ die "No handler for netroot type '$netroot'"
+ fi
+fi
+
+# Source netroot hooks before we start the handler
+source_hook netroot "$netif"
+
+# Run the handler; don't store the root, it may change from device to device
+# XXX other variables to export?
+[ -n "$handler" ] && "$handler" "$netif" "$netroot" "$NEWROOT"
+save_netinfo "$netif"
+
+exit 0
diff --git a/modules.d/45ifcfg/module-setup.sh b/modules.d/45ifcfg/module-setup.sh
new file mode 100755
index 0000000..b0d4418
--- /dev/null
+++ b/modules.d/45ifcfg/module-setup.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ [[ -d $dracutsysrootdir/etc/sysconfig/network-scripts ]] && return 0
+ return 255
+}
+
+# called by dracut
+depends() {
+ echo "network"
+ return 0
+}
+
+# called by dracut
+install() {
+ inst_binary awk
+ inst_hook pre-pivot 85 "$moddir/write-ifcfg.sh"
+}
diff --git a/modules.d/45ifcfg/write-ifcfg.sh b/modules.d/45ifcfg/write-ifcfg.sh
new file mode 100755
index 0000000..5550cce
--- /dev/null
+++ b/modules.d/45ifcfg/write-ifcfg.sh
@@ -0,0 +1,311 @@
+#!/bin/sh
+
+# NFS root might have reached here before /tmp/net.ifaces was written
+type is_persistent_ethernet_name > /dev/null 2>&1 || . /lib/net-lib.sh
+
+udevadm settle --timeout=30
+
+# shellcheck disable=SC2174
+mkdir -m 0755 -p /tmp/ifcfg/
+# shellcheck disable=SC2174
+mkdir -m 0755 -p /tmp/ifcfg-leases/
+
+get_config_line_by_subchannel() {
+ local CHANNELS
+ local line
+
+ CHANNELS="$1"
+ while read -r line || [ -n "$line" ]; do
+ if strstr "$line" "$CHANNELS"; then
+ echo "$line"
+ return 0
+ fi
+ done < /etc/ccw.conf
+ return 1
+}
+
+print_s390() {
+ local _netif
+ local SUBCHANNELS
+ local OPTIONS
+ local NETTYPE
+ local CONFIG_LINE
+ local i
+ local channel
+ local OLD_IFS
+
+ _netif="$1"
+ # if we find ccw channel, then use those, instead of
+ # of the MAC
+ SUBCHANNELS=$({
+ for i in /sys/class/net/"$_netif"/device/cdev[0-9]*; do
+ [ -e "$i" ] || continue
+ channel=$(readlink -f "$i")
+ printf '%s' "${channel##*/},"
+ done
+ })
+ [ -n "$SUBCHANNELS" ] || return 1
+
+ SUBCHANNELS=${SUBCHANNELS%,}
+ echo "SUBCHANNELS=\"${SUBCHANNELS}\""
+
+ CONFIG_LINE=$(get_config_line_by_subchannel "$SUBCHANNELS")
+ # shellcheck disable=SC2181
+ [ $? -ne 0 -o -z "$CONFIG_LINE" ] && return 0
+
+ OLD_IFS=$IFS
+ IFS=","
+ # shellcheck disable=SC2086
+ set -- $CONFIG_LINE
+ IFS=$OLD_IFS
+ NETTYPE=$1
+ shift
+ SUBCHANNELS="$1"
+ OPTIONS=""
+ shift
+ while [ $# -gt 0 ]; do
+ case $1 in
+ *=*) OPTIONS="$OPTIONS $1" ;;
+ esac
+ shift
+ done
+ OPTIONS=${OPTIONS## }
+ echo "NETTYPE=\"${NETTYPE}\""
+ echo "OPTIONS=\"${OPTIONS}\""
+ return 0
+}
+
+hw_bind() {
+ local _netif="$1"
+ local _macaddr="$2"
+
+ [ -n "$_macaddr" ] \
+ && echo "MACADDR=\"$_macaddr\""
+
+ print_s390 "$_netif" \
+ && return 0
+
+ [ -n "$_macaddr" ] && return 0
+
+ is_persistent_ethernet_name "$_netif" && return 0
+
+ [ -f "/sys/class/net/$_netif/addr_assign_type" ] \
+ && [ "$(cat "/sys/class/net/$_netif/addr_assign_type")" != "0" ] \
+ && return 1
+
+ [ -f "/sys/class/net/$_netif/address" ] \
+ || return 1
+
+ echo "HWADDR=\"$(cat /sys/class/net/"$_netif"/address)\""
+}
+
+interface_bind() {
+ local _netif="$1"
+ local _macaddr="$2"
+
+ if [ ! -e "/sys/class/net/$_netif" ]; then
+ warn "Cannot find network interface '$_netif'!"
+ return 1
+ fi
+
+ # see, if we can bind it to some hw params
+ if hw_bind "$_netif" "$_macaddr"; then
+ # only print out DEVICE, if it's user assigned
+ is_kernel_ethernet_name "$_netif" && return 0
+ fi
+
+ echo "DEVICE=\"$_netif\""
+}
+
+for netup in /tmp/net.*.did-setup; do
+ [ -f "$netup" ] || continue
+
+ netif=${netup%%.did-setup}
+ netif=${netif##*/net.}
+ strglobin "$netif" ":*:*:*:*:" && continue
+ [ -e /tmp/ifcfg/ifcfg-"$netif" ] && continue
+ unset bridge
+ unset bond
+ unset bondslaves
+ unset bondname
+ unset bondoptions
+ unset bridgename
+ unset bridgeslaves
+ unset team
+ unset uuid
+ unset ip
+ unset gw
+ unset mtu
+ unset mask
+ unset macaddr
+ unset slave
+ unset ethname
+ unset vlan
+ unset vlanname
+ unset phydevice
+
+ # shellcheck disable=SC1090
+ [ -e /tmp/bond."${netif}".info ] && . /tmp/bond."${netif}".info
+ # shellcheck disable=SC1090
+ [ -e /tmp/bridge."${netif}".info ] && . /tmp/bridge."${netif}".info
+ # shellcheck disable=SC1090
+ [ -e /tmp/team."${netif}".info ] && . /tmp/team."${netif}".info
+
+ read -r uuid < /proc/sys/kernel/random/uuid
+ if [ "$netif" = "$bridgename" ]; then
+ bridge=yes
+ elif [ "$netif" = "$teammaster" ]; then
+ team=yes
+ elif [ "$netif" = "$bondname" ]; then
+ # $netif can't be bridge and bond at the same time
+ bond=yes
+ fi
+
+ for i in "/tmp/vlan.${netif}."*; do
+ [ ! -e "$i" ] && continue
+ # shellcheck disable=SC1090
+ . "$i"
+ vlan=yes
+ break
+ done
+
+ # skip team interfaces for now, the host config must be in sync
+ [ "$netif" = "$teammaster" ] && continue
+
+ {
+ echo "# Generated by dracut initrd"
+ echo "NAME=\"$netif\""
+ [ -z "$vlan" ] && interface_bind "$netif" "$macaddr"
+ echo "ONBOOT=yes"
+ echo "NETBOOT=yes"
+ echo "UUID=\"$uuid\""
+ strstr "$(ip -6 addr show dev "$netif")" 'inet6' && echo "IPV6INIT=yes"
+ if [ -f /tmp/dhclient."$netif".lease ]; then
+ # shellcheck disable=SC1090
+ [ -f /tmp/dhclient."$netif".dhcpopts ] && . /tmp/dhclient."$netif".dhcpopts
+ if [ -f /tmp/net."$netif".has_ibft_config ]; then
+ echo "BOOTPROTO=ibft"
+ else
+ echo "BOOTPROTO=dhcp"
+ fi
+ cp /tmp/dhclient."$netif".lease /tmp/ifcfg-leases/dhclient-"$uuid"-"$netif".lease
+ else
+ # If we've booted with static ip= lines, the override file is there
+ # shellcheck disable=SC1090
+ [ -e /tmp/net."$netif".override ] && . /tmp/net."$netif".override
+ if strglobin "$ip" '*:*:*'; then
+ echo "IPV6INIT=yes"
+ echo "IPV6_AUTOCONF=no"
+ echo "IPV6ADDR=\"$ip/$mask\""
+ else
+ if [ -f /tmp/net."$netif".has_ibft_config ]; then
+ echo "BOOTPROTO=ibft"
+ else
+ echo "BOOTPROTO=none"
+ echo "IPADDR=\"$ip\""
+ if strstr "$mask" "."; then
+ echo "NETMASK=\"$mask\""
+ else
+ echo "PREFIX=\"$mask\""
+ fi
+ fi
+ fi
+ if strglobin "$gw" '*:*:*'; then
+ echo "IPV6_DEFAULTGW=\"$gw\""
+ elif [ -n "$gw" ]; then
+ echo "GATEWAY=\"$gw\""
+ fi
+ fi
+ [ -n "$mtu" ] && echo "MTU=\"$mtu\""
+ } > /tmp/ifcfg/ifcfg-"$netif"
+
+ # bridge needs different things written to ifcfg
+ if [ -z "$bridge" ] && [ -z "$bond" ] && [ -z "$vlan" ] && [ -z "$team" ]; then
+ # standard interface
+ echo "TYPE=Ethernet" >> /tmp/ifcfg/ifcfg-"$netif"
+ fi
+
+ if [ -n "$vlan" ]; then
+ {
+ echo "TYPE=Vlan"
+ echo "DEVICE=\"$netif\""
+ echo "VLAN=yes"
+ echo "PHYSDEV=\"$phydevice\""
+ } >> /tmp/ifcfg/ifcfg-"$netif"
+ fi
+
+ if [ -n "$bond" ]; then
+ # bond interface
+ {
+ # This variable is an indicator of a bond interface for initscripts
+ echo "BONDING_OPTS=\"$bondoptions\""
+ echo "NAME=\"$netif\""
+ echo "TYPE=Bond"
+ } >> /tmp/ifcfg/ifcfg-"$netif"
+
+ for slave in $bondslaves; do
+ # write separate ifcfg file for the raw eth interface
+ (
+ echo "# Generated by dracut initrd"
+ echo "NAME=\"$slave\""
+ echo "TYPE=Ethernet"
+ echo "ONBOOT=yes"
+ echo "NETBOOT=yes"
+ echo "SLAVE=yes"
+ echo "MASTER=\"$netif\""
+ echo "UUID=\"$(cat /proc/sys/kernel/random/uuid)\""
+ unset macaddr
+ # shellcheck disable=SC1090
+ [ -e /tmp/net."$slave".override ] && . /tmp/net."$slave".override
+ interface_bind "$slave" "$macaddr"
+ ) >> /tmp/ifcfg/ifcfg-"$slave"
+ done
+ fi
+
+ if [ -n "$bridge" ]; then
+ # bridge
+ {
+ echo "TYPE=Bridge"
+ echo "NAME=\"$netif\""
+ } >> /tmp/ifcfg/ifcfg-"$netif"
+ for slave in $bridgeslaves; do
+ # write separate ifcfg file for the raw eth interface
+ (
+ echo "# Generated by dracut initrd"
+ echo "NAME=\"$slave\""
+ echo "TYPE=Ethernet"
+ echo "ONBOOT=yes"
+ echo "NETBOOT=yes"
+ echo "BRIDGE=\"$bridgename\""
+ echo "UUID=\"$(cat /proc/sys/kernel/random/uuid)\""
+ unset macaddr
+ # shellcheck disable=SC1090
+ [ -e /tmp/net."$slave".override ] && . /tmp/net."$slave".override
+ interface_bind "$slave" "$macaddr"
+ ) >> /tmp/ifcfg/ifcfg-"$slave"
+ done
+ fi
+ i=1
+ for ns in $(getargs nameserver) $dns1 $dns2; do
+ echo "DNS${i}=\"${ns}\"" >> /tmp/ifcfg/ifcfg-"$netif"
+ i=$((i + 1))
+ done
+
+ [ -f /tmp/net.route6."$netif" ] && cp /tmp/net.route6."$netif" /tmp/ifcfg/route6-"$netif"
+ [ -f /tmp/net.route."$netif" ] && cp /tmp/net.route."$netif" /tmp/ifcfg/route-"$netif"
+done
+
+# Pass network opts
+mkdir -m 0755 -p /run/initramfs/state/etc/sysconfig/network-scripts
+mkdir -m 0755 -p /run/initramfs/state/var/lib/dhclient
+echo "files /etc/sysconfig/network-scripts" >> /run/initramfs/rwtab
+echo "files /var/lib/dhclient" >> /run/initramfs/rwtab
+{
+ cp /tmp/net.* /run/initramfs/
+ for i in /tmp/net.*.resolv.conf; do
+ [ -f "$i" ] && cat "$i"
+ done | awk '!($0 in a) { a[$0]; print }' > /run/initramfs/state/etc/resolv.conf
+ [ -s /run/initramfs/state/etc/resolv.conf ] || rm -f /run/initramfs/state/etc/resolv.conf
+ copytree /tmp/ifcfg /run/initramfs/state/etc/sysconfig/network-scripts
+ cp /tmp/ifcfg-leases/* /run/initramfs/state/var/lib/dhclient
+} > /dev/null 2>&1
diff --git a/modules.d/45url-lib/module-setup.sh b/modules.d/45url-lib/module-setup.sh
new file mode 100755
index 0000000..65da87e
--- /dev/null
+++ b/modules.d/45url-lib/module-setup.sh
@@ -0,0 +1,88 @@
+#!/bin/bash
+# module-setup for url-lib
+
+# called by dracut
+check() {
+ require_binaries curl || return 1
+ return 255
+}
+
+# called by dracut
+depends() {
+ echo network
+ return 0
+}
+
+# called by dracut
+install() {
+ local _dir _crt _crts _found _lib _nssckbi _p11roots _p11root
+ inst_simple "$moddir/url-lib.sh" "/lib/url-lib.sh"
+ inst_multiple -o ctorrent
+ inst_multiple curl sed
+ if curl --version | grep -qi '\bNSS\b'; then
+ # also install libs for curl https
+ inst_libdir_file "libnsspem.so*"
+ inst_libdir_file "libnsssysinit.so*"
+ inst_libdir_file "libsoftokn3.so*"
+ inst_libdir_file "libsqlite3.so*"
+ fi
+
+ for _dir in $libdirs; do
+ [[ -d $dracutsysrootdir$_dir ]] || continue
+ for _lib in "$dracutsysrootdir$_dir"/libcurl.so.* "$dracutsysrootdir$_dir"/libcrypto.so.*; do
+ [[ -e $_lib ]] || continue
+ if ! [[ $_nssckbi ]]; then
+ read -r -d '' _nssckbi < <(grep -F --binary-files=text -z libnssckbi "$_lib")
+ fi
+ read -r -d '' _crt < <(grep -E --binary-files=text -z "\.(pem|crt)" "$_lib" | sed 's/\x0//g')
+ [[ $_crt ]] || continue
+ [[ $_crt == /*/* ]] || continue
+ if [[ -e $_crt ]]; then
+ _crts="$_crts $_crt"
+ _found=1
+ fi
+ done
+ done
+ if [[ $_found ]] && [[ -n $_crts ]]; then
+ for _crt in $_crts; do
+ if ! inst "${_crt#"$dracutsysrootdir"}"; then
+ dwarn "Couldn't install '$_crt' SSL CA cert bundle; HTTPS might not work."
+ continue
+ fi
+ done
+ fi
+ # If we found no cert bundle files referenced in libcurl but we
+ # *did* find a mention of libnssckbi (checked above), install it.
+ # If its truly NSS libnssckbi, it includes its own trust bundle,
+ # but if it's really p11-kit-trust.so, we need to find the dirs
+ # where it will look for a trust bundle and install them too.
+ if ! [[ $_found ]] && [[ $_nssckbi ]]; then
+ _found=1
+ inst_libdir_file "libnssckbi.so*" || _found=
+ for _dir in $libdirs; do
+ [[ -e $dracutsysrootdir$_dir/libnssckbi.so ]] || continue
+ # this looks for directory-ish strings in the file
+ grep -z -o --binary-files=text '/[[:alpha:]][[:print:]]*' "${dracutsysrootdir}${_dir}"/libnssckbi.so \
+ | while read -r -d '' _p11roots || [[ $_p11roots ]]; do
+ IFS=":" read -r -a _p11roots <<< "$_p11roots"
+ # the string can be a :-separated list of dirs
+ for _p11root in "${_p11roots[@]}"; do
+ # check if it's actually a directory (there are
+ # several false positives in the results)
+ [[ -d "$dracutsysrootdir$_p11root" ]] || continue
+ # check if it has some specific subdirs that all
+ # p11-kit trust dirs have
+ [[ -d "$dracutsysrootdir${_p11root}/anchors" ]] || continue
+ [[ -d "$dracutsysrootdir${_p11root}/blacklist" ]] || continue
+ # so now we know it's really a p11-kit trust dir;
+ # install everything in it
+ mkdir -p -- "${initdir}/${_p11root}"
+ if ! $DRACUT_CP -L -t "${initdir}/${_p11root}" "${dracutsysrootdir}${_p11root}"/*; then
+ dwarn "Couldn't install from p11-kit trust dir '${_p11root#"$dracutsysrootdir"}'; HTTPS might not work."
+ fi
+ done
+ done
+ done
+ fi
+ [[ $_found ]] || dwarn "Couldn't find SSL CA cert bundle or libnssckbi.so; HTTPS won't work."
+}
diff --git a/modules.d/45url-lib/url-lib.sh b/modules.d/45url-lib/url-lib.sh
new file mode 100755
index 0000000..7c3ef1e
--- /dev/null
+++ b/modules.d/45url-lib/url-lib.sh
@@ -0,0 +1,174 @@
+#!/bin/sh
+# url-lib.sh - functions for handling URLs (file fetching etc.)
+#
+# Authors:
+# Will Woods <wwoods@redhat.com>
+
+type mkuniqdir > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+# fetch_url URL [OUTFILE]
+# fetch the given URL to a locally-visible location.
+# if OUTFILE is given, the URL will be fetched to that filename,
+# overwriting it if present.
+# If the URL is something mountable (e.g. nfs://) and no OUTFILE is given,
+# the server will be left mounted until pre-pivot.
+# the return values are as follows:
+# 0: success
+# 253: unknown error (file missing)
+# 254: unhandled URL scheme / protocol
+# 255: bad arguments / unparsable URLs
+# other: fetch command failure (whatever curl/mount/etc return)
+fetch_url() {
+ local url="$1" outloc="$2"
+ local handler
+ handler="$(get_url_handler "$url")"
+ [ -n "$handler" ] || return 254
+ [ -n "$url" ] || return 255
+ "$handler" "$url" "$outloc"
+}
+
+# get_url_handler URL
+# returns the first HANDLERNAME corresponding to the URL's scheme
+get_url_handler() {
+ local scheme="${1%%:*}" item=""
+ for item in $url_handler_map; do
+ [ "$scheme" = "${item%%:*}" ] && echo "${item#*:}" && return 0
+ done
+ return 1
+}
+
+# add_url_handler HANDLERNAME SCHEME [SCHEME...]
+# associate the named handler with the named scheme(s).
+add_url_handler() {
+ local handler="$1"
+ shift
+ local schemes="$*" scheme=""
+ set --
+ for scheme in $schemes; do
+ [ "$(get_url_handler "$scheme")" = "$handler" ] && continue
+ set -- "$@" "$scheme:$handler"
+ done
+ set -- "$@" "$url_handler_map" # add new items to *front* of list
+ url_handler_map="$*"
+}
+
+### HTTP, HTTPS, FTP #################################################
+
+export CURL_HOME="/run/initramfs/url-lib"
+mkdir -p $CURL_HOME
+curl_args="--globoff --location --retry 3 --retry-connrefused --fail --show-error"
+getargbool 0 rd.noverifyssl && curl_args="$curl_args --insecure"
+
+proxy=$(getarg proxy=)
+[ -n "$proxy" ] && curl_args="$curl_args --proxy $proxy"
+
+curl_fetch_url() {
+ local url="$1" outloc="$2"
+ echo "$url" > /proc/self/fd/0
+ if [ -n "$outloc" ]; then
+ # shellcheck disable=SC2086
+ curl $curl_args --output "$outloc" -- "$url" || return $?
+ else
+ local outdir
+ outdir="$(mkuniqdir /tmp curl_fetch_url)"
+ (
+ cd "$outdir" || exit
+ # shellcheck disable=SC2086
+ curl $curl_args --remote-name "$url" || return $?
+ )
+ outloc="$outdir/$(ls -A "$outdir")"
+ fi
+ if ! [ -f "$outloc" ]; then
+ warn "Downloading '$url' failed!"
+ return 253
+ fi
+ if [ -z "$2" ]; then echo "$outloc"; fi
+}
+add_url_handler curl_fetch_url http https ftp tftp
+
+set_http_header() {
+ echo "header = \"$1: $2\"" >> $CURL_HOME/.curlrc
+}
+
+### TORRENT ##########################################################
+
+ctorrent_args="-E 0 -e 0"
+
+ctorrent_fetch_url() {
+ local url="$1" outloc="$2"
+ url=${url#*//}
+ torrent_outloc="$outloc.torrent"
+ echo "$url" > /proc/self/fd/0
+ if [ -n "$outloc" ]; then
+ # shellcheck disable=SC2086
+ curl $curl_args --output "$torrent_outloc" -- "$url" || return $?
+ else
+ local outdir
+ outdir="$(mkuniqdir /tmp torrent_fetch_url)"
+ (
+ cd "$outdir" || exit
+ # shellcheck disable=SC2086
+ curl $curl_args --remote-name "$url" || return $?
+ )
+ torrent_outloc="$outdir/$(ls -A "$outdir")"
+ outloc=${torrent_outloc%.*}
+ fi
+ if ! [ -f "$torrent_outloc" ]; then
+ warn "Downloading '$url' failed!"
+ return 253
+ fi
+ # shellcheck disable=SC2086
+ ctorrent $ctorrent_args -s "$outloc" "$torrent_outloc" >&2
+ if ! [ -f "$outloc" ]; then
+ warn "Torrent download of '$url' failed!"
+ return 253
+ fi
+ if [ -z "$2" ]; then echo "$outloc"; fi
+}
+
+command -v ctorrent > /dev/null \
+ && add_url_handler ctorrent_fetch_url torrent
+
+### NFS ##############################################################
+
+[ -e /lib/nfs-lib.sh ] && . /lib/nfs-lib.sh
+
+nfs_already_mounted() {
+ local server="$1" path="$2" s="" p=""
+ while read -r src mnt rest || [ -n "$src" ]; do
+ splitsep ":" "$src" s p
+ p=${p%/}
+ if [ "$server" = "$s" ]; then
+ if [ "$path" = "$p" ]; then
+ echo "$mnt"
+ elif str_starts "$path" "$p"; then
+ echo "$mnt"/"${path#"$p"/}"
+ fi
+ fi
+ done < /proc/mounts
+}
+
+nfs_fetch_url() {
+ local url="$1" outloc="$2" nfs="" server="" path="" options=""
+ nfs_to_var "$url" || return 255
+ local filepath="${path%/*}" filename="${path##*/}" mntdir=""
+
+ # skip mount if server:/filepath is already mounted
+ mntdir=$(nfs_already_mounted "$server" "$filepath")
+ if [ -z "$mntdir" ]; then
+ local mntdir
+ mntdir="$(mkuniqdir /run nfs_mnt)"
+ mount_nfs "$nfs:$server:$filepath${options:+:$options}" "$mntdir"
+ # lazy unmount during pre-pivot hook
+ inst_hook --hook pre-pivot --name 99url-lib-umount-nfs-"$(basename "$mntdir")" umount -l -- "$mntdir"
+ fi
+
+ if [ -z "$outloc" ]; then
+ outloc="$mntdir/$filename"
+ else
+ cp -f -- "$mntdir/$filename" "$outloc" || return $?
+ fi
+ [ -f "$outloc" ] || return 253
+ if [ -z "$2" ]; then echo "$outloc"; fi
+}
+command -v nfs_to_var > /dev/null && add_url_handler nfs_fetch_url nfs nfs4
diff --git a/modules.d/50drm/module-setup.sh b/modules.d/50drm/module-setup.sh
new file mode 100755
index 0000000..1fb3867
--- /dev/null
+++ b/modules.d/50drm/module-setup.sh
@@ -0,0 +1,59 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ return 255
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ # Include KMS capable drm drivers
+
+ if [[ ${DRACUT_ARCH:-$(uname -m)} == arm* || ${DRACUT_ARCH:-$(uname -m)} == aarch64 ]]; then
+ # arm/aarch64 specific modules needed by drm
+ instmods \
+ "=drivers/gpu/drm/i2c" \
+ "=drivers/gpu/drm/panel" \
+ "=drivers/gpu/drm/bridge" \
+ "=drivers/video/backlight"
+ fi
+
+ instmods amdkfd hyperv_fb "=drivers/pwm"
+
+ # if the hardware is present, include module even if it is not currently loaded,
+ # as we could e.g. be in the installer; nokmsboot boot parameter will disable
+ # loading of the driver if needed
+ if [[ $hostonly ]]; then
+ local i modlink modname
+
+ for i in /sys/bus/{pci/devices,platform/devices,virtio/devices,soc/devices/soc?,vmbus/devices}/*/modalias; do
+ [[ -e $i ]] || continue
+ [[ -n $(< "$i") ]] || continue
+ # shellcheck disable=SC2046
+ if hostonly="" dracut_instmods --silent -s "drm_crtc_init|drm_dev_register|drm_encoder_init" -S "iw_handler_get_spy" $(< "$i"); then
+ if strstr "$(modinfo -F filename $(< "$i") 2> /dev/null)" radeon.ko; then
+ hostonly='' instmods amdkfd
+ fi
+ fi
+ done
+ # if there is a privacy screen then its driver must be loaded before the
+ # kms driver will bind, otherwise its probe() will return -EPROBE_DEFER
+ # note privacy screens always register, even with e.g. nokmsboot
+ for i in /sys/class/drm/privacy_screen-*/device/driver/module; do
+ [[ -L $i ]] || continue
+ modlink=$(readlink "$i")
+ modname=$(basename "$modlink")
+ instmods "$modname"
+ done
+ else
+ dracut_instmods -o -s "drm_crtc_init|drm_dev_register|drm_encoder_init" "=drivers/gpu/drm" "=drivers/staging"
+ # also include privacy screen providers (see above comment)
+ # atm all providers live under drivers/platform/x86
+ dracut_instmods -o -s "drm_privacy_screen_register" "=drivers/platform/x86"
+ fi
+}
diff --git a/modules.d/50plymouth/module-setup.sh b/modules.d/50plymouth/module-setup.sh
new file mode 100755
index 0000000..cc6629b
--- /dev/null
+++ b/modules.d/50plymouth/module-setup.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+
+pkglib_dir() {
+ local _dirs="/usr/lib/plymouth /usr/libexec/plymouth/"
+ if find_binary dpkg-architecture &> /dev/null; then
+ local _arch
+ _arch=$(dpkg-architecture -qDEB_HOST_MULTIARCH 2> /dev/null)
+ [ -n "$_arch" ] && _dirs+=" /usr/lib/$_arch/plymouth"
+ fi
+ for _dir in $_dirs; do
+ if [ -x "$dracutsysrootdir""$_dir"/plymouth-populate-initrd ]; then
+ echo "$_dir"
+ return
+ fi
+ done
+}
+
+# called by dracut
+check() {
+ [[ "$mount_needs" ]] && return 1
+ [[ $(pkglib_dir) ]] || return 1
+
+ require_binaries plymouthd plymouth plymouth-set-default-theme
+}
+
+# called by dracut
+depends() {
+ echo drm
+}
+
+# called by dracut
+install() {
+ PKGLIBDIR=$(pkglib_dir)
+ if grep -q nash "$dracutsysrootdir""${PKGLIBDIR}"/plymouth-populate-initrd \
+ || [ ! -x "$dracutsysrootdir""${PKGLIBDIR}"/plymouth-populate-initrd ]; then
+ # shellcheck disable=SC1090
+ . "$moddir"/plymouth-populate-initrd.sh
+ else
+ PLYMOUTH_POPULATE_SOURCE_FUNCTIONS="$dracutfunctions" \
+ "$dracutsysrootdir""${PKGLIBDIR}"/plymouth-populate-initrd -t "$initdir"
+ fi
+
+ inst_hook emergency 50 "$moddir"/plymouth-emergency.sh
+
+ inst_multiple readlink
+
+ inst_multiple plymouthd plymouth plymouth-set-default-theme
+
+ if ! dracut_module_included "systemd"; then
+ inst_hook pre-trigger 10 "$moddir"/plymouth-pretrigger.sh
+ inst_hook pre-pivot 90 "$moddir"/plymouth-newroot.sh
+ fi
+}
diff --git a/modules.d/50plymouth/plymouth-emergency.sh b/modules.d/50plymouth/plymouth-emergency.sh
new file mode 100755
index 0000000..cf220b2
--- /dev/null
+++ b/modules.d/50plymouth/plymouth-emergency.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+plymouth --hide-splash 2> /dev/null || :
diff --git a/modules.d/50plymouth/plymouth-newroot.sh b/modules.d/50plymouth/plymouth-newroot.sh
new file mode 100755
index 0000000..944f2dc
--- /dev/null
+++ b/modules.d/50plymouth/plymouth-newroot.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+if type plymouth > /dev/null 2>&1 && [ -z "$DRACUT_SYSTEMD" ]; then
+ plymouth --newroot="$NEWROOT"
+fi
diff --git a/modules.d/50plymouth/plymouth-populate-initrd.sh b/modules.d/50plymouth/plymouth-populate-initrd.sh
new file mode 100755
index 0000000..7e3afdd
--- /dev/null
+++ b/modules.d/50plymouth/plymouth-populate-initrd.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+PLYMOUTH_LOGO_FILE="/usr/share/pixmaps/system-logo-white.png"
+PLYMOUTH_THEME=$(plymouth-set-default-theme)
+
+inst_multiple plymouthd plymouth
+
+test -e "${PLYMOUTH_LOGO_FILE}" && inst_simple "${PLYMOUTH_LOGO_FILE}"
+
+# shellcheck disable=SC2174
+mkdir -m 0755 -p "${initdir}/usr/share/plymouth"
+
+inst_libdir_file "plymouth/text.so" "plymouth/details.so"
+
+if [[ $hostonly ]]; then
+ inst_multiple \
+ "/usr/share/plymouth/themes/details/details.plymouth" \
+ "/usr/share/plymouth/themes/text/text.plymouth"
+
+ if [[ -d $dracutsysrootdir/usr/share/plymouth/themes/${PLYMOUTH_THEME} ]]; then
+ for x in "/usr/share/plymouth/themes/${PLYMOUTH_THEME}"/*; do
+ [[ -f "$dracutsysrootdir$x" ]] || break
+ inst "$x"
+ done
+ fi
+
+ if [[ -L $dracutsysrootdir/usr/share/plymouth/themes/default.plymouth ]]; then
+ inst /usr/share/plymouth/themes/default.plymouth
+ # Install plugin for this theme
+ PLYMOUTH_PLUGIN=$(grep "^ModuleName=" "$dracutsysrootdir"/usr/share/plymouth/themes/default.plymouth | while read -r _ b _ || [ -n "$b" ]; do echo "$b"; done)
+ inst_libdir_file "plymouth/${PLYMOUTH_PLUGIN}.so"
+ fi
+else
+ for x in "$dracutsysrootdir"/usr/share/plymouth/themes/{text,details}/*; do
+ [[ -f $x ]] || continue
+ THEME_DIR=$(dirname "${x#"$dracutsysrootdir"}")
+ # shellcheck disable=SC2174
+ mkdir -m 0755 -p "${initdir}/$THEME_DIR"
+ inst_multiple "${x#"$dracutsysrootdir"}"
+ done
+ (
+ cd "${initdir}"/usr/share/plymouth/themes || exit
+ ln -s text/text.plymouth default.plymouth 2>&1
+ )
+fi
diff --git a/modules.d/50plymouth/plymouth-pretrigger.sh b/modules.d/50plymouth/plymouth-pretrigger.sh
new file mode 100755
index 0000000..3d11999
--- /dev/null
+++ b/modules.d/50plymouth/plymouth-pretrigger.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+if type plymouthd > /dev/null 2>&1 && [ -z "$DRACUT_SYSTEMD" ]; then
+ if getargbool 1 plymouth.enable && getargbool 1 rd.plymouth -d -n rd_NO_PLYMOUTH; then
+ # first trigger graphics subsystem
+ udevadm trigger --action=add --attr-match=class=0x030000 > /dev/null 2>&1
+ # first trigger graphics and tty subsystem
+ udevadm trigger --action=add \
+ --subsystem-match=graphics \
+ --subsystem-match=drm \
+ --subsystem-match=tty \
+ --subsystem-match=acpi \
+ > /dev/null 2>&1
+
+ udevadm settle --timeout=180 2>&1 | vinfo
+
+ info "Starting plymouth daemon"
+ mkdir -m 0755 /run/plymouth
+ read -r consoledev rest < /sys/class/tty/console/active
+ consoledev=${consoledev:-tty0}
+ [ -x /lib/udev/console_init -a -e "/dev/$consoledev" ] && /lib/udev/console_init "/dev/$consoledev"
+ plymouthd --attach-to-session --pid-file /run/plymouth/pid
+ plymouth --show-splash 2>&1 | vinfo
+ # reset tty after plymouth messed with it
+ [ -x /lib/udev/console_init -a -e "/dev/$consoledev" ] && /lib/udev/console_init "/dev/$consoledev"
+ fi
+fi
diff --git a/modules.d/62bluetooth/module-setup.sh b/modules.d/62bluetooth/module-setup.sh
new file mode 100755
index 0000000..8bef927
--- /dev/null
+++ b/modules.d/62bluetooth/module-setup.sh
@@ -0,0 +1,93 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+ # If the binary(s) requirements are not fulfilled the module can't be installed
+ require_any_binary /usr/lib/bluetooth/bluetoothd /usr/libexec/bluetooth/bluetoothd || return 1
+
+ if [[ $hostonly ]]; then
+ # Warn user if bluetooth kernel module is loaded
+ # and if Peripheral (0x500) is found of minor class:
+ # * Keyboard (0x40)
+ # * Keyboard/pointing (0xC0)
+ # and if Appearance is set to the value defined for keyboard (0x03C1)
+ [ -d "/sys/class/bluetooth" ] && grep -qiE -e 'Class=0x[0-9a-f]{3}5[4c]0' -e 'Appearance=0x03c1' /var/lib/bluetooth/*/*/info 2> /dev/null \
+ && dwarn "If you need to use bluetooth, please include it explicitly."
+ fi
+
+ return 255
+}
+
+# Module dependency requirements.
+depends() {
+ # This module has external dependencies on the systemd and dbus modules.
+ echo systemd dbus
+ # Return 0 to include the dependent modules in the initramfs.
+ return 0
+}
+
+installkernel() {
+ instmods bluetooth btrtl btintel btbcm bnep ath3k btusb rfcomm hidp
+ inst_multiple -o \
+ /lib/firmware/ar3k/AthrBT* \
+ /lib/firmware/ar3k/ramps* \
+ /lib/firmware/ath3k-1.fw* \
+ /lib/firmware/BCM2033-MD.hex* \
+ /lib/firmware/bfubase.frm* \
+ /lib/firmware/BT3CPCC.bin* \
+ /lib/firmware/brcm/*.hcd* \
+ /lib/firmware/mediatek/mt7622pr2h.bin* \
+ /lib/firmware/qca/nvm* \
+ /lib/firmware/qca/crnv* \
+ /lib/firmware/qca/rampatch* \
+ /lib/firmware/qca/crbtfw* \
+ /lib/firmware/rtl_bt/* \
+ /lib/firmware/intel/ibt* \
+ /lib/firmware/ti-connectivity/TIInit_* \
+ /lib/firmware/nokia/bcmfw.bin* \
+ /lib/firmware/nokia/ti1273.bin*
+}
+
+# Install the required file(s) for the module in the initramfs.
+install() {
+ # shellcheck disable=SC2064
+ trap "$(shopt -p globstar)" RETURN
+ shopt -q -s globstar
+ local -a var_lib_files
+
+ inst_multiple -o \
+ "$dbussystem"/bluetooth.conf \
+ "$dbussystemservices"/org.bluez.service \
+ "${systemdsystemunitdir}/bluetooth.target" \
+ "${systemdsystemunitdir}/bluetooth.service" \
+ bluetoothctl
+
+ inst_multiple -o \
+ /usr/libexec/bluetooth/bluetoothd \
+ /usr/lib/bluetooth/bluetoothd
+
+ if [[ $hostonly ]]; then
+ var_lib_files=("$dracutsysrootdir"/var/lib/bluetooth/**)
+
+ inst_multiple -o \
+ /etc/bluetooth/main.conf \
+ "$dbussystemconfdir"/bluetooth.conf \
+ "$systemdsystemconfdir"/bluetooth.service \
+ "$systemdsystemconfdir/bluetooth.service.d/*.conf" \
+ "${var_lib_files[@]#"$dracutsysrootdir"}"
+ fi
+
+ inst_rules 69-btattach-bcm.rules 60-persistent-input.rules
+
+ # shellcheck disable=SC1004
+ sed -i -e \
+ '/^\[Unit\]/aDefaultDependencies=no\
+ Conflicts=shutdown.target\
+ Before=shutdown.target\
+ After=dbus.service' \
+ "${initdir}/${systemdsystemunitdir}/bluetooth.service"
+
+ $SYSTEMCTL -q --root "$initdir" enable bluetooth.service
+}
diff --git a/modules.d/80cms/cms-write-ifcfg.sh b/modules.d/80cms/cms-write-ifcfg.sh
new file mode 100755
index 0000000..ecfd53e
--- /dev/null
+++ b/modules.d/80cms/cms-write-ifcfg.sh
@@ -0,0 +1,105 @@
+#!/bin/bash
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+OLD_UMASK=$(umask)
+umask 0022
+mkdir -p /run/initramfs/state/etc/sysconfig/network-scripts
+umask "$OLD_UMASK"
+
+function cms_write_config() {
+ . /tmp/cms.conf
+ SUBCHANNELS="$(echo "$SUBCHANNELS" | sed 'y/ABCDEF/abcdef/')"
+ OLDIFS=$IFS
+ IFS=,
+ read -ra subch_array <<< "indexzero,$SUBCHANNELS"
+ IFS=$OLDIFS
+ devbusid=${subch_array[1]}
+ if [ "$NETTYPE" = "ctc" ]; then
+ driver="ctcm"
+ else
+ driver=$NETTYPE
+ fi
+
+ DEVICE=$(cd "/sys/devices/${driver}/$devbusid/net/" && set -- * && [ "$1" != "*" ] && echo "$1")
+
+ read -r uuid < /proc/sys/kernel/random/uuid
+
+ IFCFGFILE=/run/initramfs/state/etc/sysconfig/network-scripts/ifcfg-$DEVICE
+
+ strglobin "$IPADDR" '*:*:*' && ipv6=1
+
+ # to please NetworkManager on startup in loader before loader reconfigures net
+ cat > /etc/sysconfig/network << EOF
+HOSTNAME=$HOSTNAME
+EOF
+ echo "$HOSTNAME" > /etc/hostname
+ if [ "$ipv6" ]; then
+ echo "NETWORKING_IPV6=yes" >> /etc/sysconfig/network
+ else
+ echo "NETWORKING=yes" >> /etc/sysconfig/network
+ fi
+
+ cat > "$IFCFGFILE" << EOF
+DEVICE=$DEVICE
+UUID=$uuid
+ONBOOT=yes
+BOOTPROTO=static
+MTU=$MTU
+SUBCHANNELS=$SUBCHANNELS
+EOF
+ if [ "$ipv6" ]; then
+ cat >> "$IFCFGFILE" << EOF
+IPV6INIT=yes
+IPV6_AUTOCONF=no
+IPV6ADDR=$IPADDR/$NETMASK
+IPV6_DEFAULTGW=$GATEWAY
+EOF
+ else
+ cat >> "$IFCFGFILE" << EOF
+IPADDR=$IPADDR
+NETMASK=$NETMASK
+BROADCAST=$BROADCAST
+GATEWAY=$GATEWAY
+EOF
+ fi
+ if [ "$ipv6" ]; then
+ # shellcheck disable=SC2153
+ IFS="," read -r DNS1 DNS2 _ <<< "$DNS"
+ else
+ IFS=":" read -r DNS1 DNS2 _ <<< "$DNS"
+ fi
+ # real DNS config for NetworkManager to generate /etc/resolv.conf
+ [[ $DNS1 ]] && echo "DNS1=$DNS1" >> "$IFCFGFILE"
+ [[ $DNS2 ]] && echo "DNS2=$DNS2" >> "$IFCFGFILE"
+ # just to please loader's readNetInfo && writeEnabledNetInfo
+ # which eats DNS1,DNS2,... and generates it themselves based on DNS
+ if [[ $ipv6 ]]; then
+ [[ $DNS ]] && echo "DNS=\"$DNS\"" >> "$IFCFGFILE"
+ else
+ [[ $DNS ]] && echo "DNS=\"${DNS/:/,}\"" >> "$IFCFGFILE"
+ fi
+ # colons in SEARCHDNS already replaced with spaces above for /etc/resolv.conf
+ [[ $SEARCHDNS ]] && echo "DOMAIN=\"$SEARCHDNS\"" >> "$IFCFGFILE"
+ [[ $NETTYPE ]] && echo "NETTYPE=$NETTYPE" >> "$IFCFGFILE"
+ [[ $PEERID ]] && echo "PEERID=$PEERID" >> "$IFCFGFILE"
+ [[ $PORTNAME ]] && echo "PORTNAME=$PORTNAME" >> "$IFCFGFILE"
+ [[ $CTCPROT ]] && echo "CTCPROT=$CTCPROT" >> "$IFCFGFILE"
+ [[ $MACADDR ]] && echo "MACADDR=$MACADDR" >> "$IFCFGFILE"
+ optstr=""
+ for option in LAYER2 PORTNO; do
+ [ -z "${!option}" ] && continue
+ [ -n "$optstr" ] && optstr=${optstr}" "
+ optstr=${optstr}$(echo ${option} | sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/')"="${!option}
+ done
+ # write single quotes since network.py removes double quotes but we need quotes
+ echo "OPTIONS='$optstr'" >> "$IFCFGFILE"
+ unset option
+ unset optstr
+ unset DNS1
+ unset DNS2
+ echo "files /etc/sysconfig/network-scripts" >> /run/initramfs/rwtab
+ echo "files /var/lib/dhclient" >> /run/initramfs/rwtab
+}
+
+[ -f /tmp/cms.conf ] && cms_write_config
diff --git a/modules.d/80cms/cmsifup.sh b/modules.d/80cms/cmsifup.sh
new file mode 100755
index 0000000..285e20d
--- /dev/null
+++ b/modules.d/80cms/cmsifup.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+DEVICE=$1
+
+. /tmp/cms.conf
+
+strglobin "$IPADDR" '*:*:*' && ipv6=1
+
+if [ "$ipv6" ] && ! str_starts "$IPADDR" "["; then
+ IPADDR="[$IPADDR]"
+fi
+
+if [ "$ipv6" ] && ! str_starts "$GATEWAY" "["; then
+ GATEWAY="[$GATEWAY]"
+fi
+
+if [ "$ipv6" ]; then
+ # shellcheck disable=SC2153
+ IFS="," read -r DNS1 DNS2 _ <<< "$DNS"
+else
+ IFS=":" read -r DNS1 DNS2 _ <<< "$DNS"
+fi
+
+{
+ echo "ip=$IPADDR::$GATEWAY:$NETMASK:$HOSTNAME:$DEVICE:none:$MTU:$MACADDR"
+ for i in $DNS1 $DNS2; do
+ echo "nameserver=$i"
+ done
+} > /etc/cmdline.d/80-cms.conf
+
+[ -e "/tmp/net.ifaces" ] && read -r IFACES < /tmp/net.ifaces
+IFACES="$IFACES $DEVICE"
+echo "$IFACES" >> /tmp/net.ifaces
+
+if [ -x /usr/libexec/nm-initrd-generator ] || [ -x /usr/lib/nm-initrd-generator ]; then
+ type nm_generate_connections > /dev/null 2>&1 || . /lib/nm-lib.sh
+ nm_generate_connections
+ nm_reload_connections
+else
+ exec ifup "$DEVICE"
+fi
diff --git a/modules.d/80cms/cmssetup.sh b/modules.d/80cms/cmssetup.sh
new file mode 100755
index 0000000..68e4563
--- /dev/null
+++ b/modules.d/80cms/cmssetup.sh
@@ -0,0 +1,221 @@
+#!/bin/bash
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+function sysecho() {
+ file="$1"
+ shift
+ local i=1
+ while [ $i -le 10 ]; do
+ if [ ! -f "$file" ]; then
+ sleep 1
+ i=$((i + 1))
+ else
+ break
+ fi
+ done
+ local status
+ read -r status < "$file"
+ if [[ $status != "$*" ]]; then
+ [ -f "$file" ] && echo "$*" > "$file"
+ fi
+}
+
+function dasd_settle() {
+ local dasd_status=/sys/bus/ccw/devices/$1/status
+ if [ ! -f "$dasd_status" ]; then
+ return 1
+ fi
+ local i=1
+ while [ $i -le 60 ]; do
+ local status
+ read -r status < "$dasd_status"
+ case $status in
+ online | unformatted)
+ return 0
+ ;;
+ *)
+ sleep 0.1
+ i=$((i + 1))
+ ;;
+ esac
+ done
+ return 1
+}
+
+function dasd_settle_all() {
+ for dasdccw in $(while read -r line || [ -n "$line" ]; do echo "${line%%(*}"; done < /proc/dasd/devices); do
+ if ! dasd_settle "$dasdccw"; then
+ echo $"Could not access DASD $dasdccw in time"
+ return 1
+ fi
+ done
+ return 0
+}
+
+# prints a canonocalized device bus ID for a given devno of any format
+function canonicalize_devno() {
+ case ${#1} in
+ 3) echo "0.0.0${1}" ;;
+ 4) echo "0.0.${1}" ;;
+ *) echo "${1}" ;;
+ esac
+ return 0
+}
+
+# read file from CMS and write it to /tmp
+function readcmsfile() { # $1=dasdport $2=filename
+ local dev
+ local numcpus
+ local devname
+ local ret=0
+ if [ $# -ne 2 ]; then return; fi
+ # precondition: udevd created dasda block device node
+ if ! dasd_cio_free -d "$1"; then
+ echo $"DASD $1 could not be cleared from device blacklist"
+ return 1
+ fi
+
+ modprobe dasd_mod dasd="$CMSDASD"
+ modprobe dasd_eckd_mod
+ udevadm settle
+
+ # precondition: dasd_eckd_mod driver incl. dependencies loaded,
+ # dasd_mod must be loaded without setting any DASD online
+ dev=$(canonicalize_devno "$1")
+ numcpus=$(
+ while read -r line || [ -n "$line" ]; do
+ if strstr "$line" "# processors"; then
+ echo "${line##*:}"
+ break
+ fi
+ done < /proc/cpuinfo
+ )
+
+ if [ "${numcpus}" -eq 1 ]; then
+ echo 1 > /sys/bus/ccw/devices/"$dev"/online
+ else
+ if ! sysecho /sys/bus/ccw/devices/"$dev"/online 1; then
+ echo $"DASD $dev could not be set online"
+ return 1
+ fi
+ udevadm settle
+ if ! dasd_settle "$dev"; then
+ echo $"Could not access DASD $dev in time"
+ return 1
+ fi
+ fi
+
+ udevadm settle
+
+ devname=$(
+ cd /sys/bus/ccw/devices/"$dev"/block || exit
+ set -- *
+ [ -b /dev/"$1" ] && echo "$1"
+ )
+ devname=${devname:-dasda}
+
+ [[ -d /mnt ]] || mkdir -p /mnt
+ if cmsfs-fuse --to=UTF-8 -a /dev/"$devname" /mnt; then
+ cat /mnt/"$2" > /run/initramfs/"$2"
+ umount /mnt || umount -l /mnt
+ udevadm settle
+ else
+ echo $"Could not read conf file $2 on CMS DASD $1."
+ ret=1
+ fi
+
+ if ! sysecho /sys/bus/ccw/devices/"$dev"/online 0; then
+ echo $"DASD $dev could not be set offline again"
+ #return 1
+ fi
+ udevadm settle
+
+ # unbind all dasds to unload the dasd modules for a clean start
+ (
+ cd /sys/bus/ccw/drivers/dasd-eckd || exit
+ for i in *.*; do echo "$i" > unbind; done
+ )
+ udevadm settle
+ modprobe -r dasd_eckd_mod
+ udevadm settle
+ modprobe -r dasd_diag_mod
+ udevadm settle
+ modprobe -r dasd_mod
+ udevadm settle
+ return $ret
+}
+
+processcmsfile() {
+ source /tmp/cms.conf
+ SUBCHANNELS="$(echo "$SUBCHANNELS" | sed 'y/ABCDEF/abcdef/')"
+
+ if [[ $NETTYPE ]]; then
+ (
+ echo -n "$NETTYPE","$SUBCHANNELS"
+ [[ $PORTNAME ]] && echo -n ",portname=$PORTNAME"
+ [[ $LAYER2 ]] && echo -n ",layer2=$LAYER2"
+ [[ $NETTYPE == "ctc" ]] && [[ $CTCPROT ]] && echo -n ",protocol=$CTCPROT"
+ echo
+ ) >> /etc/ccw.conf
+
+ OLDIFS=$IFS
+ IFS=,
+ read -r -a subch_array <<< "indexzero,$SUBCHANNELS"
+ IFS=$OLDIFS
+ devbusid=${subch_array[1]}
+ if [ "$NETTYPE" = "ctc" ]; then
+ driver="ctcm"
+ else
+ driver=$NETTYPE
+ fi
+
+ # shellcheck disable=SC2016
+ printf 'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="%s", KERNELS=="%s", ENV{INTERFACE}=="?*", RUN+="/sbin/initqueue --onetime --unique --name cmsifup-$name /sbin/cmsifup $name"\n' "$driver" "$devbusid" > /etc/udev/rules.d/99-cms.rules
+ # remove the default net rules
+ rm -f -- /etc/udev/rules.d/91-default-net.rules
+ # shellcheck disable=SC2016
+ [[ -f /etc/udev/rules.d/90-net.rules ]] \
+ || printf 'SUBSYSTEM=="net", ACTION=="online", RUN+="/sbin/initqueue --onetime --env netif=$name source_hook initqueue/online"\n' >> /etc/udev/rules.d/99-cms.rules
+ udevadm control --reload
+ znet_cio_free
+ fi
+
+ if [[ $DASD ]] && [[ $DASD != "none" ]]; then
+ echo "$DASD" | normalize_dasd_arg > /etc/dasd.conf
+ echo "options dasd_mod dasd=$DASD" > /etc/modprobe.d/dasd_mod.conf
+ dasd_cio_free
+ fi
+
+ unset _do_zfcp
+ for i in ${!FCP_*}; do
+ echo "${!i}" | while read -r port rest || [ -n "$port" ]; do
+ case $port in
+ *.*.*) ;;
+
+ *.*)
+ port="0.$port"
+ ;;
+ *)
+ port="0.0.$port"
+ ;;
+ esac
+ echo "$port" "$rest" >> /etc/zfcp.conf
+ done
+ _do_zfcp=1
+ done
+ [[ $_do_zfcp ]] && zfcp_cio_free
+ unset _do_zfcp
+}
+
+[[ $CMSDASD ]] || CMSDASD=$(getarg "CMSDASD=")
+[[ $CMSCONFFILE ]] || CMSCONFFILE=$(getarg "CMSCONFFILE=")
+
+# Parse configuration
+if [ -n "$CMSDASD" -a -n "$CMSCONFFILE" ]; then
+ if readcmsfile "$CMSDASD" "$CMSCONFFILE"; then
+ ln -s /run/initramfs/"$CMSCONFFILE" /tmp/"$CMSCONFFILE"
+ ln -s /run/initramfs/"$CMSCONFFILE" /tmp/cms.conf
+ processcmsfile
+ fi
+fi
diff --git a/modules.d/80cms/module-setup.sh b/modules.d/80cms/module-setup.sh
new file mode 100755
index 0000000..2b280e0
--- /dev/null
+++ b/modules.d/80cms/module-setup.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ arch=${DRACUT_ARCH:-$(uname -m)}
+ [ "$arch" = "s390" -o "$arch" = "s390x" ] || return 1
+ return 255
+}
+
+# called by dracut
+depends() {
+ arch=${DRACUT_ARCH:-$(uname -m)}
+ [ "$arch" = "s390" -o "$arch" = "s390x" ] || return 1
+ echo znet zfcp dasd dasd_mod bash
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ instmods zfcp
+}
+
+# called by dracut
+install() {
+ inst_hook pre-trigger 30 "$moddir/cmssetup.sh"
+ inst_hook pre-pivot 95 "$moddir/cms-write-ifcfg.sh"
+ inst_script "$moddir/cmsifup.sh" /sbin/cmsifup
+ # shellcheck disable=SC2046
+ inst_multiple /etc/cmsfs-fuse/filetypes.conf /etc/udev/rules.d/99-fuse.rules /etc/fuse.conf \
+ cmsfs-fuse fusermount bash insmod rmmod cat normalize_dasd_arg sed \
+ $(rpm -ql s390utils-base) awk getopt
+
+ inst_libdir_file "gconv/*"
+ #inst /usr/lib/locale/locale-archive
+ dracut_need_initqueue
+}
diff --git a/modules.d/80lvmmerge/README.md b/modules.d/80lvmmerge/README.md
new file mode 100644
index 0000000..5e3e05f
--- /dev/null
+++ b/modules.d/80lvmmerge/README.md
@@ -0,0 +1,61 @@
+# lvmmerge - dracut module
+
+## Preparation
+- ensure that the lvm thin pool is big enough
+- backup any (most likely /boot and /boot/efi) device with:
+```
+# mkdir /restoredev
+# dev=<device>; umount $dev; dd if="$dev" of=/restoredev/$(systemd-escape -p "$dev"); mount $dev
+```
+- backup the MBR
+```
+# dev=<device>; dd if="$dev" of=/restoredev/$(systemd-escape -p "$dev") bs=446 count=1
+# ls -l /dev/disk/by-path/virtio-pci-0000\:00\:07.0
+lrwxrwxrwx. 1 root root 9 Jul 24 04:27 /dev/disk/by-path/virtio-pci-0000:00:07.0 -> ../../vda
+```
+- backup some partitions
+```
+# dev=/dev/disk/by-path/virtio-pci-0000:00:07.0
+# dd if="$dev" of=/restoredev/$(systemd-escape -p "$dev") bs=446 count=1
+# umount /boot/efi
+# dev=/dev/disk/by-partuuid/687177a8-86b3-4e37-a328-91d20db9563c
+# dd if="$dev" of=/restoredev/$(systemd-escape -p "$dev")
+# umount /boot
+# dev=/dev/disk/by-partuuid/4fdf99e9-4f28-4207-a26f-c76546824eaf
+# dd if="$dev" of=/restoredev/$(systemd-escape -p "$dev")
+```
+Final /restoredev
+```
+# ls -al /restoredev/
+total 1253380
+drwx------. 2 root root 250 Jul 24 04:38 .
+dr-xr-xr-x. 18 root root 242 Jul 24 04:32 ..
+-rw-------. 1 root root 209715200 Jul 24 04:34 dev-disk-by\x2dpartuuid-4fdf99e9\x2d4f28\x2d4207\x2da26f\x2dc76546824eaf
+-rw-------. 1 root root 1073741824 Jul 24 04:34 dev-disk-by\x2dpartuuid-687177a8\x2d86b3\x2d4e37\x2da328\x2d91d20db9563c
+-rw-------. 1 root root 446 Jul 24 04:38 dev-disk-by\x2dpath-virtio\x2dpci\x2d0000:00:07.0
+```
+- make a thin snapshot
+```
+# lvm lvcreate -pr -s rhel/root --name reset
+```
+
+- mark the snapshot with a tag
+```
+# lvm lvchange --addtag reset rhel/reset
+```
+
+- remove /restoredev
+```
+# rm -fr /restoredev
+```
+
+## Operation
+
+If a boot entry with ```rd.lvm.mergetags=<tag>``` is selected and there are LVs with ```<tag>```
+dracut will
+- make a copy of the snapshot
+- merge it back to the original
+- rename the copy back to the name of the snapshot
+- if /restordev appears in the root, then it will restore the images
+ found in that directory. This can be used to restore /boot and /boot/efi and the
+ MBR of the boot device
diff --git a/modules.d/80lvmmerge/lvmmerge.sh b/modules.d/80lvmmerge/lvmmerge.sh
new file mode 100755
index 0000000..b8dbfa8
--- /dev/null
+++ b/modules.d/80lvmmerge/lvmmerge.sh
@@ -0,0 +1,95 @@
+#!/bin/bash
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+do_merge() {
+ sed -i -e 's/\(^[[:space:]]*\)locking_type[[:space:]]*=[[:space:]]*[[:digit:]]/\1locking_type = 1/' \
+ /etc/lvm/lvm.conf
+
+ systemctl --no-block stop sysroot.mount
+ swapoff -a
+ umount -R /sysroot
+
+ for tag in $(getargs rd.lvm.mergetags); do
+ lvm vgs --noheadings -o vg_name \
+ | while read -r vg || [[ -n $vg ]]; do
+ unset LVS
+ declare -a LVS
+ lvs=$(lvm lvs --noheadings -o lv_name "$vg")
+ for lv in $lvs; do
+ lvm lvchange -an "$vg/$lv"
+
+ tags=$(trim "$(lvm lvs --noheadings -o lv_tags "$vg/$lv")")
+ strstr ",${tags}," ",${tag}," || continue
+
+ if ! lvm lvs --noheadings -o lv_name "${vg}/${lv}_dracutsnap" &> /dev/null; then
+ info "Creating backup ${lv}_dracutsnap of ${vg}/${lv}"
+ lvm lvcreate -pr -s "${vg}/${lv}" --name "${lv}_dracutsnap"
+ fi
+ lvm lvchange --addtag "$tag" "${vg}/${lv}_dracutsnap"
+
+ info "Merging back ${vg}/${lv} to the original LV"
+ lvm lvconvert --merge "${vg}/${lv}"
+
+ LVS+=("$lv")
+ done
+
+ systemctl --no-block stop sysroot.mount
+ udevadm settle
+
+ for ((i = 0; i < 100; i++)); do
+ lvm vgchange -an "$vg" && break
+ sleep 0.5
+ done
+
+ udevadm settle
+ lvm vgchange -ay "$vg"
+ udevadm settle
+ for lv in "${LVS[@]}"; do
+ info "Renaming ${lv}_dracutsnap backup to ${vg}/${lv}"
+ lvm lvrename "$vg" "${lv}_dracutsnap" "${lv}"
+ done
+ udevadm settle
+ done
+ done
+
+ systemctl --no-block reset-failed systemd-fsck-root
+ systemctl --no-block start systemd-fsck-root
+ systemctl --no-block reset-failed sysroot.mount
+ systemctl --no-block start sysroot.mount
+
+ for ((i = 0; i < 100; i++)); do
+ [[ -d /sysroot/dev ]] && break
+ sleep 0.5
+ systemctl --no-block start sysroot.mount
+ done
+
+ if [[ -d /sysroot/restoredev ]]; then
+ (
+ if cd /sysroot/restoredev; then
+ # restore devices and partitions
+ for i in *; do
+ target=$(systemd-escape -pu "$i")
+ if ! [[ -b $target ]]; then
+ warn "Not restoring $target, as the device does not exist"
+ continue
+ fi
+
+ # Just in case
+ umount "$target" &> /dev/null
+
+ info "Restoring $target"
+ dd if="$i" of="$target" |& vinfo
+ done
+ fi
+ )
+ mount -o remount,rw /sysroot
+ rm -fr /sysroot/restoredev
+ fi
+ info "Rebooting"
+ reboot
+}
+
+if getarg rd.lvm.mergetags; then
+ do_merge
+fi
diff --git a/modules.d/80lvmmerge/module-setup.sh b/modules.d/80lvmmerge/module-setup.sh
new file mode 100755
index 0000000..c3be931
--- /dev/null
+++ b/modules.d/80lvmmerge/module-setup.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ # No point trying to support lvm if the binaries are missing
+ require_binaries lvm dd swapoff || return 1
+
+ return 255
+}
+
+# called by dracut
+depends() {
+ echo lvm dracut-systemd systemd bash
+ return 0
+}
+
+installkernel() {
+ hostonly="" instmods dm-snapshot
+}
+
+# called by dracut
+install() {
+ inst_multiple dd swapoff
+ inst_hook cleanup 01 "$moddir/lvmmerge.sh"
+}
diff --git a/modules.d/80lvmthinpool-monitor/module-setup.sh b/modules.d/80lvmthinpool-monitor/module-setup.sh
new file mode 100755
index 0000000..ca015bd
--- /dev/null
+++ b/modules.d/80lvmthinpool-monitor/module-setup.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ # No point trying to support lvm if the binaries are missing
+ require_binaries lvm sort tr awk || return 1
+
+ return 255
+}
+
+# called by dracut
+depends() {
+ echo lvm
+ return 0
+}
+
+# called by dracut
+install() {
+ inst_multiple sort tr awk
+ inst_script "$moddir/start-thinpool-monitor.sh" "/bin/start-thinpool-monitor"
+
+ inst "$moddir/start-thinpool-monitor.service" "$systemdsystemunitdir/start-thinpool-monitor.service"
+ $SYSTEMCTL -q --root "$initdir" add-wants initrd.target start-thinpool-monitor.service
+}
diff --git a/modules.d/80lvmthinpool-monitor/start-thinpool-monitor.service b/modules.d/80lvmthinpool-monitor/start-thinpool-monitor.service
new file mode 100644
index 0000000..97f5f1f
--- /dev/null
+++ b/modules.d/80lvmthinpool-monitor/start-thinpool-monitor.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=Lvm thinpool monitor service
+Before=initrd.target
+After=initrd-fs.target
+Conflicts=shutdown.target emergency.target
+
+[Service]
+Type=forking
+ExecStart=/bin/start-thinpool-monitor
+PIDFile=/run/thinpool-moni.pid
+StandardInput=null
+StandardOutput=journal+console
+StandardError=journal+console
+KillSignal=SIGHUP
diff --git a/modules.d/80lvmthinpool-monitor/start-thinpool-monitor.sh b/modules.d/80lvmthinpool-monitor/start-thinpool-monitor.sh
new file mode 100755
index 0000000..10f4a4b
--- /dev/null
+++ b/modules.d/80lvmthinpool-monitor/start-thinpool-monitor.sh
@@ -0,0 +1,47 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+LVS=$(getargs rd.lvm.lv -d rd_LVM_LV=)
+
+is_lvm2_thinp_device() {
+ _device_path=$1
+ _lvm2_thin_device=$(lvm lvs -S 'lv_layout=sparse && lv_layout=thin' \
+ --nosuffix --noheadings -o vg_name,lv_name "$_device_path" 2> /dev/null)
+
+ [ -n "$_lvm2_thin_device" ] && return $?
+}
+
+for LV in $LVS; do
+ if is_lvm2_thinp_device "/dev/$LV"; then
+ THIN_POOLS="$(lvm lvs -S 'lv_layout=sparse && lv_layout=thin' \
+ --nosuffix --noheadings -o vg_name,pool_lv "$LV" \
+ | awk '{printf("%s/%s",$1,$2);}') $THIN_POOLS"
+ fi
+done
+
+THIN_POOLS=$(echo "$THIN_POOLS" | tr ' ' '\n' | sort -u | tr '\n' ' ')
+
+if [ -n "$THIN_POOLS" ]; then
+ if [ -e "/etc/lvm/lvm.conf" ]; then
+ # Use 'monitoring=0' to override the value in lvm.conf, in case
+ # dmeventd monitoring been started after the calling.
+ CONFIG="activation {monitoring=0}"
+ else
+ CONFIG="activation {monitoring=0 thin_pool_autoextend_threshold=70 thin_pool_autoextend_percent=20}"
+ fi
+
+ # Activate the thinpool in case the thinpool is in inactive state.
+ # Otherwise lvextend will fail.
+ for THIN_POOL in $THIN_POOLS; do
+ lvm lvchange -ay "$THIN_POOL" --config "$CONFIG"
+ done
+
+ while true; do
+ for THIN_POOL in $THIN_POOLS; do
+ lvm lvextend --use-policies --config "$CONFIG" "$THIN_POOL"
+ done
+ sleep 5
+ done &
+ echo $! > /run/thinpool-moni.pid
+fi
diff --git a/modules.d/80test-makeroot/finished-false.sh b/modules.d/80test-makeroot/finished-false.sh
new file mode 100755
index 0000000..ecdbef9
--- /dev/null
+++ b/modules.d/80test-makeroot/finished-false.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+exit 1
diff --git a/modules.d/80test-makeroot/module-setup.sh b/modules.d/80test-makeroot/module-setup.sh
new file mode 100755
index 0000000..eb6fb74
--- /dev/null
+++ b/modules.d/80test-makeroot/module-setup.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+check() {
+ # Only include the module if another module requires it
+ return 255
+}
+
+depends() {
+ echo "dash rootfs-block kernel-modules qemu"
+}
+
+installkernel() {
+ instmods piix ide-gd_mod ata_piix ext4 sd_mod
+}
+
+install() {
+ inst_multiple poweroff cp umount sync dd
+ inst_hook initqueue/finished 01 "$moddir/finished-false.sh"
+}
diff --git a/modules.d/80test-root/module-setup.sh b/modules.d/80test-root/module-setup.sh
new file mode 100755
index 0000000..24605c5
--- /dev/null
+++ b/modules.d/80test-root/module-setup.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+check() {
+ # Only include the module if another module requires it
+ return 255
+}
+
+depends() {
+ echo "debug"
+}
+
+install() {
+ inst_simple /etc/os-release
+
+ inst_multiple mkdir ln dd stty mount poweroff umount setsid sync
+
+ for _terminfodir in /lib/terminfo /etc/terminfo /usr/share/terminfo; do
+ [ -f ${_terminfodir}/l/linux ] && break
+ done
+ inst_multiple -o ${_terminfodir}/l/linux
+
+ inst_binary "${dracutbasedir}/dracut-util" "/usr/bin/dracut-util"
+ ln -s dracut-util "${initdir}/usr/bin/dracut-getarg"
+ ln -s dracut-util "${initdir}/usr/bin/dracut-getargs"
+
+ inst_multiple -o plymouth
+}
diff --git a/modules.d/80test/hard-off.sh b/modules.d/80test/hard-off.sh
new file mode 100755
index 0000000..01acb19
--- /dev/null
+++ b/modules.d/80test/hard-off.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+getargbool 0 rd.shell || poweroff -f
+getargbool 0 failme && poweroff -f
diff --git a/modules.d/80test/module-setup.sh b/modules.d/80test/module-setup.sh
new file mode 100755
index 0000000..96041a9
--- /dev/null
+++ b/modules.d/80test/module-setup.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+check() {
+ # Only include the module if another module requires it
+ return 255
+}
+
+depends() {
+ echo "debug"
+}
+
+install() {
+ inst poweroff
+ inst_hook shutdown-emergency 000 "$moddir/hard-off.sh"
+ inst_hook emergency 000 "$moddir/hard-off.sh"
+}
diff --git a/modules.d/81cio_ignore/module-setup.sh b/modules.d/81cio_ignore/module-setup.sh
new file mode 100755
index 0000000..a54fcb9
--- /dev/null
+++ b/modules.d/81cio_ignore/module-setup.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+
+# called by dracut
+check() {
+ # do not add this module by default
+ local arch=${DRACUT_ARCH:-$(uname -m)}
+ [ "$arch" = "s390" -o "$arch" = "s390x" ] || return 1
+ return 0
+}
+
+cmdline() {
+ local cio_accept
+
+ if [ -e /boot/zipl/active_devices.txt ]; then
+ while read -r dev _; do
+ [ "$dev" = "#" -o "$dev" = "" ] && continue
+ if [ -z "$cio_accept" ]; then
+ cio_accept="$dev"
+ else
+ cio_accept="${cio_accept},${dev}"
+ fi
+ done < /boot/zipl/active_devices.txt
+ fi
+ if [ -n "$cio_accept" ]; then
+ echo "rd.cio_accept=${cio_accept}"
+ fi
+}
+
+# called by dracut
+install() {
+ if [[ $hostonly_cmdline == "yes" ]]; then
+ local _cio_accept
+ _cio_accept=$(cmdline)
+ [[ $_cio_accept ]] && printf "%s\n" "$_cio_accept" >> "${initdir}/etc/cmdline.d/01cio_accept.conf"
+ fi
+
+ inst_hook cmdline 20 "$moddir/parse-cio_accept.sh"
+ inst_multiple cio_ignore
+}
diff --git a/modules.d/81cio_ignore/parse-cio_accept.sh b/modules.d/81cio_ignore/parse-cio_accept.sh
new file mode 100755
index 0000000..6cb682a
--- /dev/null
+++ b/modules.d/81cio_ignore/parse-cio_accept.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+
+CIO_IGNORE=$(getarg cio_ignore)
+CIO_ACCEPT=$(getarg rd.cio_accept)
+
+if [ -z "$CIO_IGNORE" ]; then
+ info "cio_ignored disabled on commandline"
+ return
+fi
+if [ -n "$CIO_ACCEPT" ]; then
+ OLDIFS="$IFS"
+ IFS=,
+ # shellcheck disable=SC2086
+ set -- $CIO_ACCEPT
+ while [ "$#" -gt 0 ]; do
+ info "Enabling device $1"
+ cio_ignore --remove "$1"
+ shift
+ done
+ IFS="$OLDIFS"
+fi
diff --git a/modules.d/90btrfs/80-btrfs.rules b/modules.d/90btrfs/80-btrfs.rules
new file mode 100644
index 0000000..a2c1727
--- /dev/null
+++ b/modules.d/90btrfs/80-btrfs.rules
@@ -0,0 +1,8 @@
+SUBSYSTEM!="block", GOTO="btrfs_end"
+ACTION!="add|change", GOTO="btrfs_end"
+ENV{ID_FS_TYPE}!="btrfs", GOTO="btrfs_end"
+RUN+="/sbin/btrfs device scan $env{DEVNAME}"
+
+RUN+="/sbin/initqueue --finished --unique --name btrfs_finished /sbin/btrfs_finished"
+
+LABEL="btrfs_end"
diff --git a/modules.d/90btrfs/btrfs_device_ready.sh b/modules.d/90btrfs/btrfs_device_ready.sh
new file mode 100755
index 0000000..93d0758
--- /dev/null
+++ b/modules.d/90btrfs/btrfs_device_ready.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+btrfs_check_complete() {
+ local _rootinfo _dev
+ _dev="${1:-/dev/root}"
+ [ -e "$_dev" ] || return 0
+ _rootinfo=$(udevadm info --query=property "--name=$_dev" 2> /dev/null)
+ if strstr "$_rootinfo" "ID_FS_TYPE=btrfs"; then
+ info "Checking, if btrfs device complete"
+ btrfs device ready "$_dev" > /dev/null 2>&1
+ return $?
+ fi
+ return 0
+}
+
+btrfs_check_complete "$1"
diff --git a/modules.d/90btrfs/btrfs_finished.sh b/modules.d/90btrfs/btrfs_finished.sh
new file mode 100755
index 0000000..4606f8a
--- /dev/null
+++ b/modules.d/90btrfs/btrfs_finished.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+btrfs_check_complete() {
+ local _rootinfo _dev
+ _dev="${1:-/dev/root}"
+ [ -e "$_dev" ] || return 0
+ _rootinfo=$(udevadm info --query=property "--name=$_dev" 2> /dev/null)
+ if strstr "$_rootinfo" "ID_FS_TYPE=btrfs"; then
+ info "Checking, if btrfs device complete"
+ unset __btrfs_mount
+ mount -o ro "$_dev" /tmp > /dev/null 2>&1
+ __btrfs_mount=$?
+ [ $__btrfs_mount -eq 0 ] && umount "$_dev" > /dev/null 2>&1
+ return $__btrfs_mount
+ fi
+ return 0
+}
+
+btrfs_check_complete "$1"
diff --git a/modules.d/90btrfs/btrfs_timeout.sh b/modules.d/90btrfs/btrfs_timeout.sh
new file mode 100755
index 0000000..326231b
--- /dev/null
+++ b/modules.d/90btrfs/btrfs_timeout.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+info "Scanning for all btrfs devices"
+/sbin/btrfs device scan > /dev/null 2>&1
diff --git a/modules.d/90btrfs/module-setup.sh b/modules.d/90btrfs/module-setup.sh
new file mode 100755
index 0000000..5d88133
--- /dev/null
+++ b/modules.d/90btrfs/module-setup.sh
@@ -0,0 +1,60 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ # if we don't have btrfs installed on the host system,
+ # no point in trying to support it in the initramfs.
+ require_binaries btrfs || return 1
+
+ [[ $hostonly ]] || [[ $mount_needs ]] && {
+ for fs in "${host_fs_types[@]}"; do
+ [[ $fs == "btrfs" ]] && return 0
+ done
+ return 255
+ }
+
+ return 0
+}
+
+# called by dracut
+depends() {
+ echo udev-rules
+ return 0
+}
+
+# called by dracut
+cmdline() {
+ # Hack for slow machines
+ # see https://github.com/dracutdevs/dracut/issues/658
+ printf " rd.driver.pre=btrfs"
+}
+
+# called by dracut
+installkernel() {
+ instmods btrfs
+ printf "%s\n" "$(cmdline)" > "${initdir}/etc/cmdline.d/00-btrfs.conf"
+}
+
+# called by dracut
+install() {
+ if ! inst_rules 64-btrfs.rules; then
+ inst_rules "$moddir/80-btrfs.rules"
+ case "$(btrfs --help)" in
+ *device\ ready*)
+ inst_script "$moddir/btrfs_device_ready.sh" /sbin/btrfs_finished
+ ;;
+ *)
+ inst_script "$moddir/btrfs_finished.sh" /sbin/btrfs_finished
+ ;;
+ esac
+ else
+ inst_rules 64-btrfs-dm.rules
+ fi
+
+ if ! dracut_module_included "systemd"; then
+ inst_hook initqueue/timeout 10 "$moddir/btrfs_timeout.sh"
+ fi
+
+ inst_multiple -o btrfsck btrfs-zero-log
+ inst "$(command -v btrfs)" /sbin/btrfs
+}
diff --git a/modules.d/90crypt/crypt-cleanup.sh b/modules.d/90crypt/crypt-cleanup.sh
new file mode 100755
index 0000000..94fa724
--- /dev/null
+++ b/modules.d/90crypt/crypt-cleanup.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+# close everything which is not busy
+rm -f -- /etc/udev/rules.d/70-luks.rules > /dev/null 2>&1
+
+if ! getarg rd.luks.uuid -d rd_LUKS_UUID > /dev/null 2>&1 && getargbool 1 rd.luks -d -n rd_NO_LUKS > /dev/null 2>&1; then
+ while true; do
+ local do_break="y"
+ for i in /dev/mapper/luks-*; do
+ cryptsetup luksClose "$i" > /dev/null 2>&1 && do_break=n
+ done
+ [ "$do_break" = "y" ] && break
+ done
+fi
diff --git a/modules.d/90crypt/crypt-lib.sh b/modules.d/90crypt/crypt-lib.sh
new file mode 100755
index 0000000..f3ba20d
--- /dev/null
+++ b/modules.d/90crypt/crypt-lib.sh
@@ -0,0 +1,278 @@
+#!/bin/sh
+
+command -v getarg > /dev/null || . /lib/dracut-lib.sh
+
+# check if the crypttab contains an entry for a LUKS UUID
+crypttab_contains() {
+ local luks="$1"
+ local dev="$2"
+ local l d rest
+ if [ -f /etc/crypttab ]; then
+ while read -r l d rest || [ -n "$l" ]; do
+ strstr "${l##luks-}" "${luks##luks-}" && return 0
+ strstr "$d" "${luks##luks-}" && return 0
+ if [ -n "$dev" ]; then
+ for _dev in $(devnames "$d"); do
+ [ "$dev" -ef "$_dev" ] && return 0
+ done
+ fi
+ if [ -e /etc/block_uuid.map ]; then
+ # search for line starting with $d
+ _line=$(sed -n "\,^$d .*$,{p}" /etc/block_uuid.map)
+ [ -z "$_line" ] && continue
+ # get second column with uuid
+ _uuid="$(echo "$_line" | sed 's,^.* \(.*$\),\1,')"
+ strstr "$_uuid" "${luks##luks-}" && return 0
+ fi
+ done < /etc/crypttab
+ fi
+ return 1
+}
+
+# ask_for_password
+#
+# Wraps around plymouth ask-for-password and adds fallback to tty password ask
+# if plymouth is not present.
+#
+# --cmd command
+# Command to execute. Required.
+# --prompt prompt
+# Password prompt. Note that function already adds ':' at the end.
+# Recommended.
+# --tries n
+# How many times repeat command on its failure. Default is 3.
+# --ply-[cmd|prompt|tries]
+# Command/prompt/tries specific for plymouth password ask only.
+# --tty-[cmd|prompt|tries]
+# Command/prompt/tries specific for tty password ask only.
+# --tty-echo-off
+# Turn off input echo before tty command is executed and turn on after.
+# It's useful when password is read from stdin.
+ask_for_password() {
+ local ply_cmd
+ local ply_prompt
+ local ply_tries=3
+ local tty_cmd
+ local tty_prompt
+ local tty_tries=3
+ local ret
+
+ while [ $# -gt 0 ]; do
+ case "$1" in
+ --cmd)
+ ply_cmd="$2"
+ tty_cmd="$2"
+ shift
+ ;;
+ --ply-cmd)
+ ply_cmd="$2"
+ shift
+ ;;
+ --tty-cmd)
+ tty_cmd="$2"
+ shift
+ ;;
+ --prompt)
+ ply_prompt="$2"
+ tty_prompt="$2"
+ shift
+ ;;
+ --ply-prompt)
+ ply_prompt="$2"
+ shift
+ ;;
+ --tty-prompt)
+ tty_prompt="$2"
+ shift
+ ;;
+ --tries)
+ ply_tries="$2"
+ tty_tries="$2"
+ shift
+ ;;
+ --ply-tries)
+ ply_tries="$2"
+ shift
+ ;;
+ --tty-tries)
+ tty_tries="$2"
+ shift
+ ;;
+ --tty-echo-off) tty_echo_off=yes ;;
+ esac
+ shift
+ done
+
+ {
+ flock -s 9
+ # Prompt for password with plymouth, if installed and running.
+ if type plymouth > /dev/null 2>&1 && plymouth --ping 2> /dev/null; then
+ plymouth ask-for-password \
+ --prompt "$ply_prompt" --number-of-tries="$ply_tries" \
+ --command="$ply_cmd"
+ ret=$?
+ else
+ if [ "$tty_echo_off" = yes ]; then
+ stty_orig="$(stty -g)"
+ stty -echo
+ fi
+
+ local i=1
+ while [ $i -le "$tty_tries" ]; do
+ [ -n "$tty_prompt" ] \
+ && printf "%s" "$tty_prompt [$i/$tty_tries]:" >&2
+ eval "$tty_cmd" && ret=0 && break
+ ret=$?
+ i=$((i + 1))
+ [ -n "$tty_prompt" ] && printf '\n' >&2
+ done
+
+ [ "$tty_echo_off" = yes ] && stty "$stty_orig"
+ fi
+ } 9> /.console_lock
+
+ [ $ret -ne 0 ] && echo "Wrong password" >&2
+ return $ret
+}
+
+# Try to mount specified device (by path, by UUID or by label) and check
+# the path with 'test'.
+#
+# example:
+# test_dev -f LABEL="nice label" /some/file1
+test_dev() {
+ local test_op="$1"
+ local dev="$2"
+ local f="$3"
+ local ret=1
+ local mount_point
+
+ mount_point=$(mkuniqdir /mnt testdev)
+ [ -n "$dev" -a -n "$*" ] || return 1
+ [ -d "$mount_point" ] || die 'Mount point does not exist!'
+
+ if mount -r "$dev" "$mount_point" > /dev/null 2>&1; then
+ test "$test_op" "${mount_point}/${f}"
+ ret=$?
+ umount "$mount_point"
+ fi
+
+ rmdir "$mount_point"
+
+ return $ret
+}
+
+# match_dev devpattern dev
+#
+# Returns true if 'dev' matches 'devpattern'. Both 'devpattern' and 'dev' are
+# expanded to kernel names and then compared. If name of 'dev' is on list of
+# names of devices matching 'devpattern', the test is positive. 'dev' and
+# 'devpattern' may be anything which function 'devnames' recognizes.
+#
+# If 'devpattern' is empty or '*' then function just returns true.
+#
+# Example:
+# match_dev UUID=123 /dev/dm-1
+# Returns true if /dev/dm-1 UUID starts with "123".
+match_dev() {
+ [ -z "$1" -o "$1" = '*' ] && return 0
+ local devlist
+ local dev
+
+ devlist="$(devnames "$1")" || return 255
+ dev="$(devnames "$2")" || return 255
+
+ strstr "
+$devlist
+" "
+$dev
+"
+}
+
+# getkey keysfile for_dev
+#
+# Reads file <keysfile> produced by probe-keydev and looks for first line to
+# which device <for_dev> matches. The successful result is printed in format
+# "<keydev>:<keypath>". When nothing found, just false is returned.
+#
+# Example:
+# getkey /tmp/luks.keys /dev/sdb1
+# May print:
+# /dev/sdc1:/keys/some.key
+getkey() {
+ local keys_file="$1"
+ local for_dev="$2"
+ local luks_dev
+ local key_dev
+ local key_path
+
+ [ -z "$keys_file" -o -z "$for_dev" ] && die 'getkey: wrong usage!'
+ [ -f "$keys_file" ] || return 1
+
+ while IFS=: read -r luks_dev key_dev key_path _ || [ -n "$luks_dev" ]; do
+ if match_dev "$luks_dev" "$for_dev"; then
+ echo "${key_dev}:${key_path}"
+ return 0
+ fi
+ done < "$keys_file"
+
+ return 1
+}
+
+# readkey keypath keydev device
+#
+# Mounts <keydev>, reads key from file <keypath>, optionally processes it (e.g.
+# if encrypted with GPG) and prints to standard output which is supposed to be
+# read by cryptsetup. <device> is just passed to helper function for
+# informational purpose.
+readkey() {
+ local keypath="$1"
+ local keydev="$2"
+ local device="$3"
+
+ # No mounting needed if the keyfile resides inside the initrd
+ if [ "/" = "$keydev" ]; then
+ local mntp=/
+ else
+ # This creates a unique single mountpoint for *, or several for explicitly
+ # given LUKS devices. It accomplishes unlocking multiple LUKS devices with
+ # a single password entry.
+ local mntp
+ mntp="/mnt/$(str_replace "keydev-$keydev-$keypath" '/' '-')"
+
+ if [ ! -d "$mntp" ]; then
+ mkdir -p "$mntp"
+ mount -r "$keydev" "$mntp" || die 'Mounting rem. dev. failed!'
+ fi
+ fi
+
+ case "${keypath##*.}" in
+ gpg)
+ if [ -f /lib/dracut-crypt-gpg-lib.sh ]; then
+ . /lib/dracut-crypt-gpg-lib.sh
+ gpg_decrypt "$mntp" "$keypath" "$keydev" "$device"
+ else
+ die "No GPG support to decrypt '$keypath' on '$keydev'."
+ fi
+ ;;
+ img)
+ if [ -f /lib/dracut-crypt-loop-lib.sh ]; then
+ . /lib/dracut-crypt-loop-lib.sh
+ loop_decrypt "$mntp" "$keypath" "$keydev" "$device"
+ printf "%s\n" "umount \"$mntp\"; rmdir \"$mntp\";" > "${hookdir}/cleanup/crypt-loop-cleanup-99-${mntp##*/}".sh
+ return 0
+ else
+ die "No loop file support to decrypt '$keypath' on '$keydev'."
+ fi
+ ;;
+ *) cat "$mntp/$keypath" ;;
+ esac
+
+ # No unmounting if the keyfile resides inside the initrd
+ if [ "/" != "$keydev" ]; then
+ # General unmounting mechanism, modules doing custom cleanup should return earlier
+ # and install a pre-pivot cleanup hook
+ umount "$mntp"
+ rmdir "$mntp"
+ fi
+}
diff --git a/modules.d/90crypt/crypt-run-generator.sh b/modules.d/90crypt/crypt-run-generator.sh
new file mode 100755
index 0000000..3e78e6d
--- /dev/null
+++ b/modules.d/90crypt/crypt-run-generator.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+. /lib/dracut-lib.sh
+type crypttab_contains > /dev/null 2>&1 || . /lib/dracut-crypt-lib.sh
+
+dev=$1
+luks=$2
+
+crypttab_contains "$luks" "$dev" && exit 0
+
+allowdiscards="-"
+
+# parse for allow-discards
+if [ -n "$DRACUT_SYSTEMD" ] || strstr "$(cryptsetup --help)" "allow-discards"; then
+ if discarduuids=$(getargs "rd.luks.allow-discards"); then
+ discarduuids=$(str_replace "$discarduuids" 'luks-' '')
+ if strstr " $discarduuids " " ${luks##luks-}"; then
+ allowdiscards="discard"
+ fi
+ elif getargbool 0 rd.luks.allow-discards; then
+ allowdiscards="discard"
+ fi
+fi
+
+echo "$luks $dev - timeout=0,$allowdiscards" >> /etc/crypttab
+
+if command -v systemctl > /dev/null; then
+ systemctl daemon-reload
+ systemctl start cryptsetup.target
+fi
+exit 0
diff --git a/modules.d/90crypt/cryptroot-ask.sh b/modules.d/90crypt/cryptroot-ask.sh
new file mode 100755
index 0000000..b1f8df8
--- /dev/null
+++ b/modules.d/90crypt/cryptroot-ask.sh
@@ -0,0 +1,207 @@
+#!/bin/sh
+
+PATH=/usr/sbin:/usr/bin:/sbin:/bin
+NEWROOT=${NEWROOT:-"/sysroot"}
+
+# do not ask, if we already have root
+[ -f "$NEWROOT"/proc ] && exit 0
+
+. /lib/dracut-lib.sh
+
+mkdir -p -m 0700 /run/cryptsetup
+
+# if device name is /dev/dm-X, convert to /dev/mapper/name
+if [ "${1##/dev/dm-}" != "$1" ]; then
+ device="/dev/mapper/$(dmsetup info -c --noheadings -o name "$1")"
+else
+ device="$1"
+fi
+
+# default luksname - luks-UUID
+luksname=$2
+
+# is_keysource - ask for passphrase even if a rd.luks.key argument is set
+is_keysource=${3:-0}
+
+# number of tries
+numtries=${4:-10}
+
+# TODO: improve to support what cmdline does
+if [ -f /etc/crypttab ] && getargbool 1 rd.luks.crypttab -d -n rd_NO_CRYPTTAB; then
+ while read -r name dev luksfile luksoptions || [ -n "$name" ]; do
+ # ignore blank lines and comments
+ if [ -z "$name" -o "${name#\#}" != "$name" ]; then
+ continue
+ fi
+
+ # PARTUUID used in crypttab
+ if [ "${dev%%=*}" = "PARTUUID" ]; then
+ if [ "luks-${dev##PARTUUID=}" = "$luksname" ]; then
+ luksname="$name"
+ break
+ fi
+
+ # UUID used in crypttab
+ elif [ "${dev%%=*}" = "UUID" ]; then
+ if [ "luks-${dev##UUID=}" = "$luksname" ]; then
+ luksname="$name"
+ break
+ fi
+
+ # ID used in crypttab
+ elif [ "${dev%%=*}" = "ID" ]; then
+ if [ "luks-${dev##ID=}" = "$luksname" ]; then
+ luksname="$name"
+ break
+ fi
+
+ # path used in crypttab
+ else
+ cdev=$(readlink -f "$dev")
+ mdev=$(readlink -f "$device")
+ if [ "$cdev" = "$mdev" ]; then
+ luksname="$name"
+ break
+ fi
+ fi
+ done < /etc/crypttab
+ unset name dev
+fi
+
+# check if destination already exists
+[ -b /dev/mapper/"$luksname" ] && exit 0
+
+# we already asked for this device
+asked_file=/tmp/cryptroot-asked-$luksname
+[ -f "$asked_file" ] && exit 0
+
+# load dm_crypt if it is not already loaded
+[ -d /sys/module/dm_crypt ] || modprobe dm_crypt
+
+. /lib/dracut-crypt-lib.sh
+
+#
+# Open LUKS device
+#
+
+info "luksOpen $device $luksname $luksfile $luksoptions"
+
+OLD_IFS="$IFS"
+IFS=,
+# shellcheck disable=SC2086
+set -- $luksoptions
+IFS="$OLD_IFS"
+
+while [ $# -gt 0 ]; do
+ case $1 in
+ noauto)
+ # skip this
+ exit 0
+ ;;
+ swap)
+ # skip this
+ exit 0
+ ;;
+ tmp)
+ # skip this
+ exit 0
+ ;;
+ allow-discards)
+ allowdiscards="--allow-discards"
+ ;;
+ header=*)
+ cryptsetupopts="${cryptsetupopts} --${1}"
+ ;;
+ esac
+ shift
+done
+
+# parse for allow-discards
+if strstr "$(cryptsetup --help)" "allow-discards"; then
+ if discarduuids=$(getargs "rd.luks.allow-discards"); then
+ discarduuids=$(str_replace "$discarduuids" 'luks-' '')
+ if strstr " $discarduuids " " ${luksdev##luks-}"; then
+ allowdiscards="--allow-discards"
+ fi
+ elif getargbool 0 rd.luks.allow-discards; then
+ allowdiscards="--allow-discards"
+ fi
+fi
+
+if strstr "$(cryptsetup --help)" "allow-discards"; then
+ cryptsetupopts="$cryptsetupopts $allowdiscards"
+fi
+
+unset allowdiscards
+
+# fallback to passphrase
+ask_passphrase=1
+
+if [ -n "$luksfile" -a "$luksfile" != "none" -a -e "$luksfile" ]; then
+ # shellcheck disable=SC2086
+ if readkey "$luksfile" / "$device" \
+ | cryptsetup -d - $cryptsetupopts luksOpen "$device" "$luksname"; then
+ ask_passphrase=0
+ fi
+elif [ "$is_keysource" -ne 0 ]; then
+ info "Asking for passphrase because $device is a keysource."
+else
+ while [ -n "$(getarg rd.luks.key)" ]; do
+ if tmp=$(getkey /tmp/luks.keys "$device"); then
+ keydev="${tmp%%:*}"
+ keypath="${tmp#*:}"
+ else
+ if [ "$numtries" -eq 0 ]; then
+ warn "No key found for $device. Fallback to passphrase mode."
+ break
+ fi
+ sleep 1
+ info "No key found for $device. Will try $numtries time(s) more later."
+ initqueue --unique --onetime --settled \
+ --name cryptroot-ask-"$luksname" \
+ "$(command -v cryptroot-ask)" "$device" "$luksname" "$is_keysource" "$((numtries - 1))"
+ exit 0
+ fi
+ unset tmp
+
+ info "Using '$keypath' on '$keydev'"
+ # shellcheck disable=SC2086
+ readkey "$keypath" "$keydev" "$device" \
+ | cryptsetup -d - $cryptsetupopts luksOpen "$device" "$luksname" \
+ && ask_passphrase=0
+ unset keypath keydev
+ break
+ done
+fi
+
+if [ $ask_passphrase -ne 0 ]; then
+ luks_open="$(command -v cryptsetup) $cryptsetupopts luksOpen"
+ _timeout=$(getargs "rd.luks.timeout")
+ _timeout=${_timeout:-0}
+ ask_for_password --ply-tries 5 \
+ --ply-cmd "$luks_open -T1 $device $luksname" \
+ --ply-prompt "Password ($device)" \
+ --tty-tries 1 \
+ --tty-cmd "$luks_open -T5 -t $_timeout $device $luksname"
+ unset luks_open
+ unset _timeout
+fi
+
+if [ "$is_keysource" -ne 0 -a "${luksname##luks-}" != "$luksname" ]; then
+ luks_close="$(command -v cryptsetup) close"
+ {
+ printf -- '[ -e /dev/mapper/%s ] && ' "$luksname"
+ printf -- '%s "%s"\n' "$luks_close" "$luksname"
+ } >> "$hookdir/cleanup/31-crypt-keysource.sh"
+ unset luks_close
+fi
+
+unset device luksname luksfile
+
+# mark device as asked
+: >> "$asked_file"
+
+need_shutdown
+udevsettle
+
+exit 0
diff --git a/modules.d/90crypt/module-setup.sh b/modules.d/90crypt/module-setup.sh
new file mode 100755
index 0000000..d5ac45b
--- /dev/null
+++ b/modules.d/90crypt/module-setup.sh
@@ -0,0 +1,186 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ local fs
+ # if cryptsetup is not installed, then we cannot support encrypted devices.
+ require_any_binary "$systemdutildir"/systemd-cryptsetup cryptsetup || return 1
+
+ [[ $hostonly ]] || [[ $mount_needs ]] && {
+ for fs in "${host_fs_types[@]}"; do
+ [[ $fs == "crypto_LUKS" ]] && return 0
+ done
+ return 255
+ }
+
+ return 0
+}
+
+# called by dracut
+depends() {
+ local deps
+ deps="dm rootfs-block"
+ if [[ $hostonly && -f "$dracutsysrootdir"/etc/crypttab ]]; then
+ if grep -q -e "fido2-device=" -e "fido2-cid=" "$dracutsysrootdir"/etc/crypttab; then
+ deps+=" fido2"
+ fi
+ if grep -q "pkcs11-uri" "$dracutsysrootdir"/etc/crypttab; then
+ deps+=" pkcs11"
+ fi
+ if grep -q "tpm2-device=" "$dracutsysrootdir"/etc/crypttab; then
+ deps+=" tpm2-tss"
+ fi
+ fi
+ echo "$deps"
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ hostonly="" instmods drbg
+ instmods dm_crypt
+
+ # in case some of the crypto modules moved from compiled in
+ # to module based, try to install those modules
+ # best guess
+ if [[ $hostonly ]] || [[ $mount_needs ]]; then
+ # dmsetup returns s.th. like
+ # cryptvol: 0 2064384 crypt aes-xts-plain64 :64:logon:cryptsetup:....
+ dmsetup table | while read -r name _ _ is_crypt cipher _; do
+ [[ $is_crypt == "crypt" ]] || continue
+ # get the device name
+ name=/dev/$(dmsetup info -c --noheadings -o blkdevname "${name%:}")
+ # check if the device exists as a key in our host_fs_types (even with null string)
+ # shellcheck disable=SC2030 # this is a shellcheck bug
+ if [[ ${host_fs_types[$name]+_} ]]; then
+ # split the cipher aes-xts-plain64 in pieces
+ IFS='-:' read -ra mods <<< "$cipher"
+ # try to load the cipher part with "crypto-" prepended
+ # in non-hostonly mode
+ hostonly='' instmods "${mods[@]/#/crypto-}" "crypto-$cipher"
+ fi
+ done
+ else
+ instmods "=crypto"
+ fi
+ return 0
+}
+
+# called by dracut
+cmdline() {
+ local dev UUID
+ # shellcheck disable=SC2031
+ for dev in "${!host_fs_types[@]}"; do
+ [[ ${host_fs_types[$dev]} != "crypto_LUKS" ]] && continue
+
+ UUID=$(
+ blkid -u crypto -o export "$dev" \
+ | while read -r line || [ -n "$line" ]; do
+ [[ ${line#UUID} == "$line" ]] && continue
+ printf "%s" "${line#UUID=}"
+ break
+ done
+ )
+ [[ ${UUID} ]] || continue
+ printf "%s" " rd.luks.uuid=luks-${UUID}"
+ done
+}
+
+# called by dracut
+install() {
+
+ if [[ $hostonly_cmdline == "yes" ]]; then
+ local _cryptconf
+ _cryptconf=$(cmdline)
+ [[ $_cryptconf ]] && printf "%s\n" "$_cryptconf" >> "${initdir}/etc/cmdline.d/90crypt.conf"
+ fi
+
+ inst_hook cmdline 30 "$moddir/parse-crypt.sh"
+ if ! dracut_module_included "systemd"; then
+ inst_multiple cryptsetup rmdir readlink umount
+ inst_script "$moddir"/cryptroot-ask.sh /sbin/cryptroot-ask
+ inst_script "$moddir"/probe-keydev.sh /sbin/probe-keydev
+ inst_hook cmdline 10 "$moddir/parse-keydev.sh"
+ inst_hook cleanup 30 "$moddir/crypt-cleanup.sh"
+ fi
+
+ if [[ $hostonly ]] && [[ -f $dracutsysrootdir/etc/crypttab ]]; then
+ # filter /etc/crypttab for the devices we need
+ while read -r _mapper _dev _luksfile _luksoptions || [ -n "$_mapper" ]; do
+ [[ $_mapper == \#* ]] && continue
+ [[ $_dev ]] || continue
+
+ [[ $_dev == PARTUUID=* ]] \
+ && _dev="/dev/disk/by-partuuid/${_dev#PARTUUID=}"
+
+ [[ $_dev == UUID=* ]] \
+ && _dev="/dev/disk/by-uuid/${_dev#UUID=}"
+
+ [[ $_dev == ID=* ]] \
+ && _dev="/dev/disk/by-id/${_dev#ID=}"
+
+ echo "$_dev $(blkid "$_dev" -s UUID -o value)" >> "${initdir}/etc/block_uuid.map"
+
+ # loop through the options to check for the force option
+ luksoptions=${_luksoptions}
+ OLD_IFS="${IFS}"
+ IFS=,
+ # shellcheck disable=SC2086
+ set -- ${luksoptions}
+ IFS="${OLD_IFS}"
+
+ forceentry=""
+ while [ $# -gt 0 ]; do
+ case $1 in
+ force)
+ forceentry="yes"
+ break
+ ;;
+ esac
+ shift
+ done
+
+ # include the entry regardless
+ if [ "${forceentry}" = "yes" ]; then
+ echo "$_mapper $_dev $_luksfile $_luksoptions"
+ else
+ # shellcheck disable=SC2031
+ for _hdev in "${!host_fs_types[@]}"; do
+ [[ ${host_fs_types[$_hdev]} == "crypto_LUKS" ]] || continue
+ if [[ $_hdev -ef $_dev ]] || [[ /dev/block/$_hdev -ef $_dev ]]; then
+ echo "$_mapper $_dev $_luksfile $_luksoptions"
+ break
+ fi
+ done
+ fi
+ done < "$dracutsysrootdir"/etc/crypttab > "$initdir"/etc/crypttab
+ mark_hostonly /etc/crypttab
+ fi
+
+ inst_simple "$moddir/crypt-lib.sh" "/lib/dracut-crypt-lib.sh"
+ inst_script "$moddir/crypt-run-generator.sh" "/sbin/crypt-run-generator"
+
+ if dracut_module_included "systemd"; then
+ # the cryptsetup targets are already pulled in by 00systemd, but not
+ # the enablement symlinks
+ inst_multiple -o \
+ "$tmpfilesdir"/cryptsetup.conf \
+ "$systemdutildir"/system-generators/systemd-cryptsetup-generator \
+ "$systemdutildir"/systemd-cryptsetup \
+ "$systemdsystemunitdir"/systemd-ask-password-console.path \
+ "$systemdsystemunitdir"/systemd-ask-password-console.service \
+ "$systemdsystemunitdir"/cryptsetup.target \
+ "$systemdsystemunitdir"/sysinit.target.wants/cryptsetup.target \
+ "$systemdsystemunitdir"/remote-cryptsetup.target \
+ "$systemdsystemunitdir"/initrd-root-device.target.wants/remote-cryptsetup.target \
+ systemd-ask-password systemd-tty-ask-password-agent
+ fi
+
+ # Install required libraries.
+ _arch=${DRACUT_ARCH:-$(uname -m)}
+ inst_libdir_file \
+ {"tls/$_arch/",tls/,"$_arch/",}"/ossl-modules/fips.so" \
+ {"tls/$_arch/",tls/,"$_arch/",}"/ossl-modules/legacy.so"
+
+ dracut_need_initqueue
+}
diff --git a/modules.d/90crypt/parse-crypt.sh b/modules.d/90crypt/parse-crypt.sh
new file mode 100755
index 0000000..e46e347
--- /dev/null
+++ b/modules.d/90crypt/parse-crypt.sh
@@ -0,0 +1,197 @@
+#!/bin/sh
+
+type crypttab_contains > /dev/null 2>&1 || . /lib/dracut-crypt-lib.sh
+
+_cryptgetargsname() {
+ debug_off
+ local _o _found _key
+ unset _o
+ unset _found
+ _key="$1"
+ set --
+ for _o in $(getargs rd.luks.name); do
+ if [ "${_o%=*}" = "${_key%=}" ]; then
+ [ -n "${_o%=*}" ] && set -- "$@" "${_o#*=}"
+ _found=1
+ fi
+ done
+ if [ -n "$_found" ]; then
+ [ $# -gt 0 ] && printf '%s' "$*"
+ return 0
+ fi
+ return 1
+}
+
+if ! getargbool 1 rd.luks -d -n rd_NO_LUKS; then
+ info "rd.luks=0: removing cryptoluks activation"
+ rm -f -- /etc/udev/rules.d/70-luks.rules
+else
+ {
+ echo 'SUBSYSTEM!="block", GOTO="luks_end"'
+ echo 'ACTION!="add|change", GOTO="luks_end"'
+ } > /etc/udev/rules.d/70-luks.rules.new
+
+ PARTUUID=$(getargs rd.luks.partuuid -d rd_LUKS_PARTUUID)
+ SERIAL=$(getargs rd.luks.serial -d rd_LUKS_SERIAL)
+ LUKS=$(getargs rd.luks.uuid -d rd_LUKS_UUID)
+ tout=$(getarg rd.luks.key.tout)
+
+ if [ -e /etc/crypttab ]; then
+ while read -r _ _dev _ || [ -n "$_dev" ]; do
+ set_systemd_timeout_for_dev "$_dev"
+ done < /etc/crypttab
+ fi
+
+ if [ -n "$PARTUUID" ]; then
+ for uuid in $PARTUUID; do
+
+ is_keysource=0
+ _uuid=$uuid
+ uuid=${uuid#keysource:}
+ [ "$uuid" != "$_uuid" ] && is_keysource=1
+ unset _uuid
+
+ uuid=${uuid##luks-}
+ if luksname=$(_cryptgetargsname "$uuid="); then
+ luksname="${luksname#"$uuid"=}"
+ else
+ luksname="luks-$uuid"
+ fi
+
+ if [ -z "$DRACUT_SYSTEMD" ]; then
+ {
+ printf -- 'ENV{ID_PART_ENTRY_UUID}=="*%s*", ' "$uuid"
+ printf -- 'RUN+="%s --settled --unique --onetime ' "$(command -v initqueue)"
+ printf -- '--name cryptroot-ask-%%k %s ' "$(command -v cryptroot-ask)"
+ # shellcheck disable=SC2016
+ printf -- '$env{DEVNAME} %s %s %s"\n' "$luksname" "$is_keysource" "$tout"
+ } >> /etc/udev/rules.d/70-luks.rules.new
+ else
+ luksname=$(dev_unit_name "$luksname")
+ # shellcheck disable=SC1003
+ luksname="$(str_replace "$luksname" '\' '\\')"
+
+ if ! crypttab_contains "$uuid"; then
+ {
+ printf -- 'ENV{ID_PART_ENTRY_UUID}=="*%s*", ' "$uuid"
+ printf -- 'RUN+="%s --settled --unique --onetime ' "$(command -v initqueue)"
+ printf -- '--name systemd-cryptsetup-%%k %s start ' "$(command -v systemctl)"
+ printf -- 'systemd-cryptsetup@%s.service"\n' "$luksname"
+ } >> /etc/udev/rules.d/70-luks.rules.new
+ fi
+ fi
+ done
+
+ elif [ -n "$SERIAL" ]; then
+ for serialid in $SERIAL; do
+
+ is_keysource=0
+ _serialid=$serialid
+ serialid=${serialid#keysource:}
+ [ "$serialid" != "$_serialid" ] && is_keysource=1
+ unset _serialid
+
+ serialid=${serialid##luks-}
+ if luksname=$(_cryptgetargsname "$serialid="); then
+ luksname="${luksname#"$serialid"=}"
+ else
+ luksname="luks-$serialid"
+ fi
+
+ if [ -z "$DRACUT_SYSTEMD" ]; then
+ {
+ printf -- 'ENV{ID_SERIAL_SHORT}=="*%s*", ' "$serialid"
+ printf -- 'RUN+="%s --settled --unique --onetime ' "$(command -v initqueue)"
+ printf -- '--name cryptroot-ask-%%k %s ' "$(command -v cryptroot-ask)"
+ # shellcheck disable=SC2016
+ printf -- '$env{DEVNAME} %s %s %s"\n' "$luksname" "$is_keysource" "$tout"
+ } >> /etc/udev/rules.d/70-luks.rules.new
+ else
+ luksname=$(dev_unit_name "$luksname")
+ # shellcheck disable=SC1003
+ luksname="$(str_replace "$luksname" '\' '\\')"
+
+ if ! crypttab_contains "$serialid"; then
+ {
+ printf -- 'ENV{ID_SERIAL_SHORT}=="*%s*", ' "$serialid"
+ printf -- 'RUN+="%s --settled --unique --onetime ' "$(command -v initqueue)"
+ printf -- '--name systemd-cryptsetup-%%k %s start ' "$(command -v systemctl)"
+ printf -- 'systemd-cryptsetup@%s.service"\n' "$luksname"
+ } >> /etc/udev/rules.d/70-luks.rules.new
+ fi
+ fi
+ done
+
+ elif [ -n "$LUKS" ]; then
+ for luksid in $LUKS; do
+
+ is_keysource=0
+ _luksid=$luksid
+ luksid=${luksid#keysource:}
+ [ "$luksid" != "$_luksid" ] && is_keysource=1
+ unset _luksid
+
+ luksid=${luksid##luks-}
+ if luksname=$(_cryptgetargsname "$luksid="); then
+ luksname="${luksname#"$luksid"=}"
+ else
+ luksname="luks-$luksid"
+ fi
+
+ if [ -z "$DRACUT_SYSTEMD" ]; then
+ {
+ printf -- 'ENV{ID_FS_TYPE}=="crypto_LUKS", '
+ printf -- 'ENV{ID_FS_UUID}=="*%s*", ' "$luksid"
+ printf -- 'RUN+="%s --settled --unique --onetime ' "$(command -v initqueue)"
+ printf -- '--name cryptroot-ask-%%k %s ' "$(command -v cryptroot-ask)"
+ # shellcheck disable=SC2016
+ printf -- '$env{DEVNAME} %s %s %s"\n' "$luksname" "$is_keysource" "$tout"
+ } >> /etc/udev/rules.d/70-luks.rules.new
+ else
+ luksname=$(dev_unit_name "$luksname")
+ # shellcheck disable=SC1003
+ luksname="$(str_replace "$luksname" '\' '\\')"
+
+ if ! crypttab_contains "$luksid"; then
+ {
+ printf -- 'ENV{ID_FS_TYPE}=="crypto_LUKS", '
+ printf -- 'ENV{ID_FS_UUID}=="*%s*", ' "$luksid"
+ printf -- 'RUN+="%s --settled --unique --onetime ' "$(command -v initqueue)"
+ printf -- '--name systemd-cryptsetup-%%k %s start ' "$(command -v systemctl)"
+ printf -- 'systemd-cryptsetup@%s.service"\n' "$luksname"
+ } >> /etc/udev/rules.d/70-luks.rules.new
+ fi
+ fi
+
+ if [ $is_keysource -eq 0 ]; then
+ uuid=$luksid
+ while [ "$uuid" != "${uuid#*-}" ]; do uuid=${uuid%%-*}${uuid#*-}; done
+ printf -- '[ -e /dev/disk/by-id/dm-uuid-CRYPT-LUKS?-*%s*-* ] || exit 1\n' "$uuid" \
+ >> "$hookdir/initqueue/finished/90-crypt.sh"
+ {
+ printf -- '[ -e /dev/disk/by-uuid/*%s* ] || ' "$luksid"
+ printf -- 'warn "crypto LUKS UUID "%s" not found"\n' "$luksid"
+ } >> "$hookdir/emergency/90-crypt.sh"
+ fi
+ done
+ elif getargbool 0 rd.auto; then
+ if [ -z "$DRACUT_SYSTEMD" ]; then
+ {
+ printf -- 'ENV{ID_FS_TYPE}=="crypto_LUKS", RUN+="%s ' "$(command -v initqueue)"
+ printf -- '--unique --settled --onetime --name cryptroot-ask-%%k '
+ # shellcheck disable=SC2016
+ printf -- '%s $env{DEVNAME} luks-$env{ID_FS_UUID} 0 %s"\n' "$(command -v cryptroot-ask)" "$tout"
+ } >> /etc/udev/rules.d/70-luks.rules.new
+ else
+ {
+ printf -- 'ENV{ID_FS_TYPE}=="crypto_LUKS", RUN+="%s ' "$(command -v initqueue)"
+ printf -- '--unique --settled --onetime --name crypt-run-generator-%%k '
+ # shellcheck disable=SC2016
+ printf -- '%s $env{DEVNAME} luks-$env{ID_FS_UUID}"\n' "$(command -v crypt-run-generator)"
+ } >> /etc/udev/rules.d/70-luks.rules.new
+ fi
+ fi
+
+ echo 'LABEL="luks_end"' >> /etc/udev/rules.d/70-luks.rules.new
+ mv /etc/udev/rules.d/70-luks.rules.new /etc/udev/rules.d/70-luks.rules
+fi
diff --git a/modules.d/90crypt/parse-keydev.sh b/modules.d/90crypt/parse-keydev.sh
new file mode 100755
index 0000000..467d892
--- /dev/null
+++ b/modules.d/90crypt/parse-keydev.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+if getargbool 1 rd.luks -n rd_NO_LUKS \
+ && [ -n "$(getarg rd.luks.key)" ]; then
+ exec 7> /etc/udev/rules.d/65-luks-keydev.rules
+ echo 'SUBSYSTEM!="block", GOTO="luks_keydev_end"' >&7
+ echo 'ACTION!="add|change", GOTO="luks_keydev_end"' >&7
+
+ for arg in $(getargs rd.luks.key); do
+ unset keypath keydev luksdev
+ splitsep : "$arg" keypath keydev luksdev
+
+ info "rd.luks.key: keypath='$keypath' keydev='$keydev' luksdev='$luksdev'"
+
+ if [ -z "$keypath" ]; then
+ warn 'keypath required!'
+ continue
+ fi
+
+ # A keydev of '/' is treated as the initrd itself
+ if [ "/" = "$keydev" ]; then
+ [ -z "$luksdev" ] && luksdev='*'
+ echo "$luksdev:$keydev:$keypath" >> /tmp/luks.keys
+ continue
+ elif [ -n "$keydev" ]; then
+ udevmatch "$keydev" >&7 || {
+ warn 'keydev incorrect!'
+ continue
+ }
+ printf ', ' >&7
+ fi
+
+ {
+ printf -- 'RUN+="%s --unique --onetime ' "$(command -v initqueue)"
+ printf -- '--name probe-keydev-%%k '
+ printf -- '%s /dev/%%k %s %s"\n' \
+ "$(command -v probe-keydev)" "${keypath}" "${luksdev}"
+ } >&7
+ done
+ unset arg keypath keydev luksdev
+
+ echo 'LABEL="luks_keydev_end"' >&7
+ exec 7>&-
+fi
diff --git a/modules.d/90crypt/probe-keydev.sh b/modules.d/90crypt/probe-keydev.sh
new file mode 100755
index 0000000..e5a3f36
--- /dev/null
+++ b/modules.d/90crypt/probe-keydev.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+. /lib/dracut-crypt-lib.sh
+
+real_keydev="$1"
+keypath="$2"
+luksdev="$3"
+
+[ -z "$real_keydev" -o -z "$keypath" ] && die 'probe-keydev: wrong usage!'
+[ -z "$luksdev" ] && luksdev='*'
+
+info "Probing $real_keydev for $keypath..."
+test_dev -f "$real_keydev" "$keypath" || exit 1
+
+info "Found $keypath on $real_keydev"
+echo "$luksdev:$real_keydev:$keypath" >> /tmp/luks.keys
diff --git a/modules.d/90dm/11-dm.rules b/modules.d/90dm/11-dm.rules
new file mode 100644
index 0000000..89941c4
--- /dev/null
+++ b/modules.d/90dm/11-dm.rules
@@ -0,0 +1,5 @@
+SUBSYSTEM!="block", GOTO="dm_end"
+KERNEL!="dm-[0-9]*", GOTO="dm_end"
+ACTION!="add|change", GOTO="dm_end"
+OPTIONS+="db_persist"
+LABEL="dm_end"
diff --git a/modules.d/90dm/59-persistent-storage-dm.rules b/modules.d/90dm/59-persistent-storage-dm.rules
new file mode 100644
index 0000000..3e0b8f6
--- /dev/null
+++ b/modules.d/90dm/59-persistent-storage-dm.rules
@@ -0,0 +1,15 @@
+SUBSYSTEM!="block", GOTO="dm_end"
+ACTION!="add|change", GOTO="dm_end"
+# Also don't process disks that are slated to be a multipath device
+ENV{DM_MULTIPATH_DEVICE_PATH}=="1", GOTO="dm_end"
+
+KERNEL!="dm-[0-9]*", GOTO="dm_end"
+ACTION=="add", GOTO="dm_end"
+IMPORT{program}="/sbin/dmsetup info -c --nameprefixes --unquoted --rows --noheadings -o name,uuid,suspended,readonly,major,minor,open,tables_loaded,names_using_dev -j%M -m%m"
+ENV{DM_NAME}!="?*", GOTO="dm_end"
+ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", GOTO="dm_end"
+ENV{DM_UUID}=="CRYPT-TEMP-?*", GOTO="dm_end"
+ENV{DM_UUID}!="?*", ENV{DM_NAME}=="temporary-cryptsetup-?*", GOTO="dm_end"
+IMPORT{builtin}="blkid"
+
+LABEL="dm_end"
diff --git a/modules.d/90dm/dm-pre-udev.sh b/modules.d/90dm/dm-pre-udev.sh
new file mode 100755
index 0000000..ba8d962
--- /dev/null
+++ b/modules.d/90dm/dm-pre-udev.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+strstr "$(cat /proc/misc)" device-mapper || modprobe dm_mod
+modprobe dm_mirror 2> /dev/null
diff --git a/modules.d/90dm/dm-shutdown.sh b/modules.d/90dm/dm-shutdown.sh
new file mode 100755
index 0000000..bd7134a
--- /dev/null
+++ b/modules.d/90dm/dm-shutdown.sh
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+_remove_dm() {
+ local dev="$1"
+ local s
+ local devname
+
+ for s in /sys/block/"${dev}"/holders/dm-*; do
+ [ -e "${s}" ] || continue
+ _remove_dm "${s##*/}"
+ done
+ # multipath devices might have MD devices on top,
+ # which are removed after this script. So do not
+ # remove those to avoid spurious errors
+ case $(cat /sys/block/"${dev}"/dm/uuid) in
+ mpath-*)
+ return 0
+ ;;
+ *)
+ read -r devname < /sys/block/"${dev}"/dm/name
+ dmsetup -v --noudevsync remove "$devname" || return $?
+ ;;
+ esac
+ return 0
+}
+
+_do_dm_shutdown() {
+ local ret=0
+ local final="$1"
+ local dev
+
+ info "Disassembling device-mapper devices"
+ for dev in /sys/block/dm-*; do
+ [ -e "${dev}" ] || continue
+ if [ "x$final" != "x" ]; then
+ _remove_dm "${dev##*/}" || ret=$?
+ else
+ _remove_dm "${dev##*/}" > /dev/null 2>&1 || ret=$?
+ fi
+ done
+ if [ "x$final" != "x" ]; then
+ info "dmsetup ls --tree"
+ dmsetup ls --tree 2>&1 | vinfo
+ fi
+ return $ret
+}
+
+if command -v dmsetup > /dev/null \
+ && [ "x$(dmsetup status)" != "xNo devices found" ]; then
+ _do_dm_shutdown "$1"
+else
+ :
+fi
diff --git a/modules.d/90dm/module-setup.sh b/modules.d/90dm/module-setup.sh
new file mode 100755
index 0000000..0c4cba3
--- /dev/null
+++ b/modules.d/90dm/module-setup.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ require_binaries dmsetup || return 1
+ return 255
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ instmods '=drivers/md' dm_mod dm-cache dm-cache-mq dm-cache-cleaner
+}
+
+# called by dracut
+install() {
+ modinfo -k "$kernel" dm_mod > /dev/null 2>&1 \
+ && inst_hook pre-udev 30 "$moddir/dm-pre-udev.sh"
+
+ inst_multiple dmsetup
+
+ inst_rules 10-dm.rules 13-dm-disk.rules 95-dm-notify.rules
+ # Gentoo ebuild for LVM2 prior to 2.02.63-r1 doesn't install above rules
+ # files, but provides the one below:
+ inst_rules 64-device-mapper.rules
+ # debian udev rules
+ inst_rules 60-persistent-storage-dm.rules 55-dm.rules
+
+ inst_rules "$moddir/11-dm.rules"
+
+ inst_rules "$moddir/59-persistent-storage-dm.rules"
+
+ inst_hook shutdown 25 "$moddir/dm-shutdown.sh"
+}
diff --git a/modules.d/90dmraid/61-dmraid-imsm.rules b/modules.d/90dmraid/61-dmraid-imsm.rules
new file mode 100644
index 0000000..8a6b215
--- /dev/null
+++ b/modules.d/90dmraid/61-dmraid-imsm.rules
@@ -0,0 +1,28 @@
+# This file causes block devices with RAID (dmraid) signatures to
+# automatically cause dmraid_scan to be run.
+# See udev(8) for syntax
+
+SUBSYSTEM!="block", GOTO="dm_end"
+ACTION!="add|change", GOTO="dm_end"
+# Also don't process disks that are slated to be a multipath device
+ENV{DM_MULTIPATH_DEVICE_PATH}=="1", GOTO="dm_end"
+
+ENV{ID_FS_TYPE}=="linux_raid_member", GOTO="dm_end"
+
+ENV{ID_FS_TYPE}!="*_raid_member", GOTO="dm_end"
+
+ENV{ID_FS_TYPE}=="isw_raid_member", ENV{rd_NO_MDIMSM}!="?*", GOTO="dm_end"
+ENV{ID_FS_TYPE}=="ddf_raid_member", ENV{rd_NO_MDDDF}!="?*", GOTO="dm_end"
+
+ENV{rd_NO_DM}=="?*", GOTO="dm_end"
+
+OPTIONS:="nowatch"
+
+ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", GOTO="dm_end"
+
+PROGRAM=="/bin/sh -c 'for i in $sys/$devpath/holders/dm-[0-9]*; do [ -e $$i ] && exit 0; done; exit 1;' ", \
+ GOTO="dm_end"
+
+RUN+="/sbin/initqueue --onetime --unique --settled /sbin/dmraid_scan $env{DEVNAME}"
+
+LABEL="dm_end"
diff --git a/modules.d/90dmraid/dmraid.sh b/modules.d/90dmraid/dmraid.sh
new file mode 100755
index 0000000..b517320
--- /dev/null
+++ b/modules.d/90dmraid/dmraid.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+devenc=$(str_replace "$1" '/' '\2f')
+
+[ -e /tmp/dmraid."$devenc" ] && exit 0
+
+: > /tmp/dmraid."$devenc"
+
+DM_RAIDS=$(getargs rd.dm.uuid -d rd_DM_UUID=)
+
+if [ -n "$DM_RAIDS" ] || getargbool 0 rd.auto; then
+ # run dmraid if udev has settled
+ info "Scanning for dmraid devices $DM_RAIDS"
+ SETS=$(dmraid -c -s)
+
+ if [ "$SETS" = "no raid disks" -o "$SETS" = "no raid sets" ]; then
+ return
+ fi
+
+ info "Found dmraid sets:"
+ echo "$SETS" | vinfo
+
+ if [ -n "$DM_RAIDS" ]; then
+ # only activate specified DM RAIDS
+ for r in $DM_RAIDS; do
+ for s in $SETS; do
+ if [ "${s##"$r"}" != "$s" ]; then
+ info "Activating $s"
+ dmraid -ay -i -p --rm_partitions "$s" 2>&1 | vinfo
+ fi
+ done
+ done
+ else
+ # scan and activate all DM RAIDS
+ for s in $SETS; do
+ info "Activating $s"
+ dmraid -ay -i -p --rm_partitions "$s" 2>&1 | vinfo
+ [ -e "/dev/mapper/$s" ] && kpartx -a "/dev/mapper/$s" 2>&1 | vinfo
+ udevsettle
+ done
+ fi
+
+ need_shutdown
+fi
diff --git a/modules.d/90dmraid/module-setup.sh b/modules.d/90dmraid/module-setup.sh
new file mode 100755
index 0000000..482ae96
--- /dev/null
+++ b/modules.d/90dmraid/module-setup.sh
@@ -0,0 +1,87 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ local holder
+ local dev
+
+ # if we don't have dmraid installed on the host system, no point
+ # in trying to support it in the initramfs.
+ require_binaries dmraid || return 1
+ require_binaries kpartx || return 1
+
+ [[ $hostonly ]] || [[ $mount_needs ]] && {
+ for dev in "${!host_fs_types[@]}"; do
+ [[ ${host_fs_types[$dev]} != *_raid_member ]] && continue
+
+ DEVPATH=$(get_devpath_block "$dev")
+
+ for holder in "$DEVPATH"/holders/*; do
+ [[ -e $holder ]] || continue
+ [[ -e "$holder/dm" ]] && return 0
+ break
+ done
+
+ done
+ return 255
+ }
+
+ return 0
+}
+
+# called by dracut
+depends() {
+ echo dm rootfs-block
+ return 0
+}
+
+# called by dracut
+cmdline() {
+ local dev
+ local -A _activated
+
+ for dev in "${!host_fs_types[@]}"; do
+ local holder DEVPATH DM_NAME
+ [[ ${host_fs_types[$dev]} != *_raid_member ]] && continue
+
+ DEVPATH=$(get_devpath_block "$dev")
+
+ for holder in "$DEVPATH"/holders/*; do
+ [[ -e $holder ]] || continue
+ dev="/dev/${holder##*/}"
+ DM_NAME="$(dmsetup info -c --noheadings -o name "$dev" 2> /dev/null)"
+ [[ ${DM_NAME} ]] && break
+ done
+
+ [[ ${DM_NAME} ]] || continue
+
+ if ! [[ ${_activated[${DM_NAME}]} ]]; then
+ printf "%s" " rd.dm.uuid=${DM_NAME}"
+ _activated["${DM_NAME}"]=1
+ fi
+ done
+}
+
+# called by dracut
+install() {
+ local _raidconf
+
+ if [[ $hostonly_cmdline == "yes" ]]; then
+ _raidconf=$(cmdline)
+ [[ $_raidconf ]] && printf "%s\n" "$_raidconf" >> "${initdir}/etc/cmdline.d/90dmraid.conf"
+ fi
+
+ inst_multiple dmraid
+ inst_multiple -o kpartx
+ inst "$(command -v partx)" /sbin/partx
+
+ inst "$moddir/dmraid.sh" /sbin/dmraid_scan
+
+ inst_rules 66-kpartx.rules 67-kpartx-compat.rules
+
+ inst_libdir_file "libdmraid-events*.so*"
+
+ inst_rules "$moddir/61-dmraid-imsm.rules"
+ #inst "$moddir/dmraid-cleanup.sh" /sbin/dmraid-cleanup
+ inst_hook pre-trigger 30 "$moddir/parse-dm.sh"
+}
diff --git a/modules.d/90dmraid/parse-dm.sh b/modules.d/90dmraid/parse-dm.sh
new file mode 100755
index 0000000..d7a6b69
--- /dev/null
+++ b/modules.d/90dmraid/parse-dm.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+# nodmraid for anaconda / rc.sysinit compatibility
+if ! getargbool 1 rd.dm -d -n rd_NO_DM || getarg "rd.dm=0" -d nodmraid; then
+ info "rd.dm=0: removing DM RAID activation"
+ udevproperty rd_NO_DM=1
+fi
+
+if ! command -v mdadm > /dev/null \
+ || ! getargbool 1 rd.md.imsm -d -n rd_NO_MDIMSM -n noiswmd \
+ || ! getargbool 1 rd.md -d -n rd_NO_MD; then
+ info "rd.md.imsm=0: no MD RAID for imsm/isw raids"
+ udevproperty rd_NO_MDIMSM=1
+fi
+
+if ! command -v mdadm > /dev/null \
+ || ! getargbool 1 rd.md.ddf -n rd_NO_MDDDF -n noddfmd \
+ || ! getargbool 1 rd.md -d -n rd_NO_MD; then
+ info "rd.md.ddf=0: no MD RAID for SNIA ddf raids"
+ udevproperty rd_NO_MDDDF=1
+fi
+
+DM_RAIDS=$(getargs rd.dm.uuid -d rd_DM_UUID=)
+
+if [ -z "$DM_RAIDS" ] && ! getargbool 0 rd.auto; then
+ udevproperty rd_NO_DM=1
+fi
diff --git a/modules.d/90dmsquash-live-autooverlay/create-overlay-genrules.sh b/modules.d/90dmsquash-live-autooverlay/create-overlay-genrules.sh
new file mode 100755
index 0000000..8372b50
--- /dev/null
+++ b/modules.d/90dmsquash-live-autooverlay/create-overlay-genrules.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+case "$root" in
+ live:/dev/*)
+ printf 'SYMLINK=="%s", RUN+="/sbin/initqueue --settled --onetime --unique /sbin/create-overlay %s"\n' \
+ "${root#live:/dev/}" "${root#live:}" >> /etc/udev/rules.d/95-create-overlay.rules
+ wait_for_dev -n "${root#live:}"
+ ;;
+esac
diff --git a/modules.d/90dmsquash-live-autooverlay/create-overlay.sh b/modules.d/90dmsquash-live-autooverlay/create-overlay.sh
new file mode 100755
index 0000000..10e8ea5
--- /dev/null
+++ b/modules.d/90dmsquash-live-autooverlay/create-overlay.sh
@@ -0,0 +1,119 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+if getargbool 0 rd.live.debug -n -y rdlivedebug; then
+ exec > /tmp/create-overlay.$$.out
+ exec 2>> /tmp/create-overlay.$$.out
+ set -x
+fi
+
+gatherData() {
+ overlay=$(getarg rd.live.overlay)
+ if [ -z "$overlay" ]; then
+ info "Skipping overlay creation: kernel command line parameter 'rd.live.overlay' is not set"
+ exit 0
+ fi
+ # shellcheck disable=SC2086
+ if ! str_starts ${overlay} LABEL=; then
+ die "Overlay creation failed: the partition must be set by LABEL in the 'rd.live.overlay' kernel parameter"
+ fi
+
+ overlayLabel=${overlay#LABEL=}
+ # shellcheck disable=SC2086
+ if [ -b /dev/disk/by-label/${overlayLabel} ]; then
+ info "Skipping overlay creation: overlay already exists"
+ exit 0
+ fi
+
+ filesystem=$(getarg rd.live.overlay.cowfs)
+ [ -z "$filesystem" ] && filesystem="ext4"
+ if [ "$filesystem" != "ext4" ] && [ "$filesystem" != "xfs" ] && [ "$filesystem" != "btrfs" ]; then
+ die "Overlay creation failed: only ext4, xfs, and btrfs are supported in the 'rd.live.overlay.cowfs' kernel parameter"
+ fi
+
+ live_dir=$(getarg rd.live.dir)
+ [ -z "$live_dir" ] && live_dir="LiveOS"
+
+ [ -z "$1" ] && exit 1
+ rootDevice=$1
+
+ # The kernel command line's 'root=' parameter was parsed into the $root variable by the dmsquash-live module.
+ # $root contains the path to a symlink within /dev/disk/by-label, which points to a partition.
+ # This script needs that partition's parent block device.
+ # shellcheck disable=SC2046
+ # shellcheck disable=SC2086
+ rootDeviceAbsolutePath=$(readlink -f ${rootDevice})
+ rootDeviceSysfsPath=/sys/class/block/${rootDeviceAbsolutePath##*/}
+ if [ -f "${rootDeviceSysfsPath}/partition" ]; then
+ # shellcheck disable=SC2086
+ read -r partition < ${rootDeviceSysfsPath}/partition
+ else
+ partition=0
+ fi
+ # shellcheck disable=SC2086
+ read -r readonly < ${rootDeviceSysfsPath}/ro
+ # shellcheck disable=SC2086
+ if [ "$partition" != "1" ] || [ "$readonly" != "0" ]; then
+ info "Skipping overlay creation: unpartitioned or read-only media detected"
+ exit 0
+ fi
+ # shellcheck disable=SC2046
+ # shellcheck disable=SC2086
+ fullDriveSysfsPath=$(readlink -f ${rootDeviceSysfsPath}/..)
+ blockDevice=/dev/${fullDriveSysfsPath##*/}
+ currentPartitionCount=$(grep --count -E "${blockDevice#/dev/}[0-9]+" /proc/partitions)
+
+ # shellcheck disable=SC2086
+ freeSpaceStart=$(parted --script ${blockDevice} unit % print free \
+ | awk -v x=${currentPartitionCount} '$1 == x {getline; print $1}')
+ if [ -z "$freeSpaceStart" ]; then
+ info "Skipping overlay creation: there is no free space after the last partition"
+ exit 0
+ fi
+ partitionStart=$((${freeSpaceStart%.*} + 1))
+ if [ $partitionStart -eq 100 ]; then
+ info "Skipping overlay creation: there is not enough free space after the last partition"
+ exit 0
+ fi
+
+ overlayPartition=${blockDevice}$((currentPartitionCount + 1))
+
+ label=$(blkid --match-tag LABEL --output value "$rootDevice")
+ uuid=$(blkid --match-tag UUID --output value "$rootDevice")
+ if [ -z "$label" ] || [ -z "$uuid" ]; then
+ die "Overlay creation failed: failed to look up root device label and UUID"
+ fi
+}
+
+createPartition() {
+ # shellcheck disable=SC2086
+ parted --script --align optimal ${blockDevice} mkpart primary ${partitionStart}% 100%
+}
+
+createFilesystem() {
+ # shellcheck disable=SC2086
+ mkfs.${filesystem} -L ${overlayLabel} ${overlayPartition}
+
+ baseDir=/run/initramfs/create-overlayfs
+ mkdir -p ${baseDir}
+ # shellcheck disable=SC2086
+ mount -t ${filesystem} ${overlayPartition} ${baseDir}
+
+ mkdir -p ${baseDir}/${live_dir}/ovlwork
+ # shellcheck disable=SC2086
+ mkdir ${baseDir}/${live_dir}/overlay-${label}-${uuid}
+
+ umount ${baseDir}
+ rm -r ${baseDir}
+}
+
+main() {
+ gatherData "$1"
+ createPartition
+ udevsettle
+ createFilesystem
+ udevsettle
+}
+
+main "$1"
diff --git a/modules.d/90dmsquash-live-autooverlay/module-setup.sh b/modules.d/90dmsquash-live-autooverlay/module-setup.sh
new file mode 100755
index 0000000..a97ca5a
--- /dev/null
+++ b/modules.d/90dmsquash-live-autooverlay/module-setup.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+check() {
+ # including a module dedicated to live environments in a host-only initrd doesn't make sense
+ [[ $hostonly ]] && return 1
+ return 255
+}
+
+depends() {
+ echo dmsquash-live
+ return 0
+}
+
+installkernel() {
+ instmods btrfs ext4 xfs
+}
+
+install() {
+ inst_multiple awk blkid cat grep mkdir mount parted readlink rmdir tr umount
+ inst_multiple -o mkfs.btrfs mkfs.ext4 mkfs.xfs
+ inst_hook pre-udev 25 "$moddir/create-overlay-genrules.sh"
+ inst_script "$moddir/create-overlay.sh" "/sbin/create-overlay"
+ dracut_need_initqueue
+}
diff --git a/modules.d/90dmsquash-live-ntfs/module-setup.sh b/modules.d/90dmsquash-live-ntfs/module-setup.sh
new file mode 100755
index 0000000..7aa5802
--- /dev/null
+++ b/modules.d/90dmsquash-live-ntfs/module-setup.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+check() {
+ require_binaries ntfs-3g || return 1
+ return 255
+}
+
+depends() {
+ echo dmsquash-live
+ return 0
+}
+
+install() {
+ inst_multiple fusermount mount.fuse ntfs-3g
+ inst_script "$moddir/mount-ntfs-3g.sh" "/sbin/mount-ntfs-3g"
+ dracut_need_initqueue
+}
+
+installkernel() {
+ hostonly='' instmods fuse
+}
diff --git a/modules.d/90dmsquash-live-ntfs/mount-ntfs-3g.sh b/modules.d/90dmsquash-live-ntfs/mount-ntfs-3g.sh
new file mode 100755
index 0000000..289205c
--- /dev/null
+++ b/modules.d/90dmsquash-live-ntfs/mount-ntfs-3g.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+type vwarn > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+# Symlinking /usr/bin/ntfs-3g as /sbin/mount.ntfs seems to boot
+# at the first glance, but ends with lots and lots of squashfs
+# errors, because systemd attempts to kill the ntfs-3g process?!
+# See https://systemd.io/ROOT_STORAGE_DAEMONS/
+if [ -x "/usr/bin/ntfs-3g" ]; then
+ (
+ ln -s /usr/bin/ntfs-3g /run/@ntfs-3g
+ (sleep 1 && rm /run/@ntfs-3g) &
+ # shellcheck disable=SC2123
+ PATH=/run
+ exec @ntfs-3g "$@"
+ ) | vwarn
+else
+ die "Failed to mount block device of live image: Missing NTFS support"
+ exit 1
+fi
diff --git a/modules.d/90dmsquash-live/apply-live-updates.sh b/modules.d/90dmsquash-live/apply-live-updates.sh
new file mode 100755
index 0000000..a5a5a39
--- /dev/null
+++ b/modules.d/90dmsquash-live/apply-live-updates.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+if [ -h /dev/root ] && [ -d /run/initramfs/live/updates -o -d /updates ]; then
+ info "Applying updates to live image..."
+ mount -o bind /run "$NEWROOT"/run
+ # avoid overwriting symlinks (e.g. /lib -> /usr/lib) with directories
+ for d in /updates /run/initramfs/live/updates; do
+ [ -d "$d" ] || continue
+ (
+ cd "$d" || return 0
+ find . -depth -type d -exec mkdir -p "$NEWROOT/{}" \;
+ find . -depth \! -type d -exec cp -a "{}" "$NEWROOT/{}" \;
+ )
+ done
+ umount "$NEWROOT"/run
+fi
+# release resources on iso-scan boots with rd.live.ram
+if [ -d /run/initramfs/isoscan ] \
+ && [ -f /run/initramfs/squashed.img -o -f /run/initramfs/rootfs.img ]; then
+ umount --detach-loop /run/initramfs/live
+ umount /run/initramfs/isoscan
+fi
diff --git a/modules.d/90dmsquash-live/checkisomd5@.service b/modules.d/90dmsquash-live/checkisomd5@.service
new file mode 100644
index 0000000..c4ca10f
--- /dev/null
+++ b/modules.d/90dmsquash-live/checkisomd5@.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=Media check on %f
+DefaultDependencies=no
+Before=shutdown.target
+
+[Service]
+Type=oneshot
+RemainAfterExit=no
+ExecStart=/bin/checkisomd5 --verbose %f
+StandardInput=tty-force
+StandardOutput=inherit
+StandardError=inherit
+TimeoutSec=0
+SuccessExitStatus=2
diff --git a/modules.d/90dmsquash-live/dmsquash-generator.sh b/modules.d/90dmsquash-live/dmsquash-generator.sh
new file mode 100755
index 0000000..8e3dfe8
--- /dev/null
+++ b/modules.d/90dmsquash-live/dmsquash-generator.sh
@@ -0,0 +1,80 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+[ -z "$root" ] && root=$(getarg root=)
+
+# support legacy syntax of passing liveimg and then just the base root
+if getargbool 0 rd.live.image -d -y liveimg; then
+ liveroot="live:$root"
+fi
+
+if [ "${root%%:*}" = "live" ]; then
+ liveroot=$root
+fi
+
+[ "${liveroot%%:*}" = "live" ] || exit 0
+
+case "$liveroot" in
+ live:LABEL=* | LABEL=* | live:UUID=* | UUID=* | live:PARTUUID=* | PARTUUID=* | live:PARTLABEL=* | PARTLABEL=*)
+ root="live:$(label_uuid_to_dev "${root#live:}")"
+ rootok=1
+ ;;
+ live:CDLABEL=* | CDLABEL=*)
+ root="${root#live:}"
+ root="$(echo "$root" | sed 's,/,\\x2f,g;s, ,\\x20,g')"
+ root="live:/dev/disk/by-label/${root#CDLABEL=}"
+ rootok=1
+ ;;
+ live:/*.[Ii][Ss][Oo] | /*.[Ii][Ss][Oo])
+ root="${root#live:}"
+ root="liveiso:${root}"
+ rootok=1
+ ;;
+ live:/dev/*)
+ rootok=1
+ ;;
+ live:/*.[Ii][Mm][Gg] | /*.[Ii][Mm][Gg])
+ [ -f "${root#live:}" ] && rootok=1
+ ;;
+esac
+
+[ "$rootok" != "1" ] && exit 0
+
+GENERATOR_DIR="$2"
+[ -z "$GENERATOR_DIR" ] && exit 1
+[ -d "$GENERATOR_DIR" ] || mkdir -p "$GENERATOR_DIR"
+
+getargbool 0 rd.live.overlay.readonly -d -y readonly_overlay && readonly_overlay="--readonly" || readonly_overlay=""
+getargbool 0 rd.live.overlay.overlayfs && overlayfs="yes"
+[ -e /xor_overlayfs ] && xor_overlayfs="yes"
+[ -e /xor_readonly ] && xor_readonly="--readonly"
+ROOTFLAGS="$(getarg rootflags)"
+{
+ echo "[Unit]"
+ echo "Before=initrd-root-fs.target"
+ echo "[Mount]"
+ echo "Where=/sysroot"
+ if [ "$overlayfs$xor_overlayfs" = "yes" ]; then
+ echo "What=LiveOS_rootfs"
+ if [ "$readonly_overlay$xor_readonly" = "--readonly" ]; then
+ ovlfs=lowerdir=/run/overlayfs-r:/run/rootfsbase
+ else
+ ovlfs=lowerdir=/run/rootfsbase
+ fi
+ echo "Options=${ROOTFLAGS},${ovlfs},upperdir=/run/overlayfs,workdir=/run/ovlwork"
+ echo "Type=overlay"
+ _dev=LiveOS_rootfs
+ else
+ echo "What=/dev/mapper/live-rw"
+ [ -n "$ROOTFLAGS" ] && echo "Options=${ROOTFLAGS}"
+ _dev='dev-mapper-live\x2drw'
+ fi
+} > "$GENERATOR_DIR"/sysroot.mount
+
+mkdir -p "$GENERATOR_DIR/$_dev.device.d"
+{
+ echo "[Unit]"
+ echo "JobTimeoutSec=3000"
+ echo "JobRunningTimeoutSec=3000"
+} > "$GENERATOR_DIR/$_dev.device.d/timeout.conf"
diff --git a/modules.d/90dmsquash-live/dmsquash-live-genrules.sh b/modules.d/90dmsquash-live/dmsquash-live-genrules.sh
new file mode 100755
index 0000000..8c7cad8
--- /dev/null
+++ b/modules.d/90dmsquash-live/dmsquash-live-genrules.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+case "$root" in
+ live:/dev/*)
+ {
+ printf 'KERNEL=="%s", RUN+="/sbin/initqueue --settled --onetime --unique /sbin/dmsquash-live-root %s"\n' \
+ "${root#live:/dev/}" "${root#live:}"
+ printf 'SYMLINK=="%s", RUN+="/sbin/initqueue --settled --onetime --unique /sbin/dmsquash-live-root %s"\n' \
+ "${root#live:/dev/}" "${root#live:}"
+ } >> /etc/udev/rules.d/99-live-squash.rules
+ wait_for_dev -n "${root#live:}"
+ ;;
+ live:*)
+ if [ -f "${root#live:}" ]; then
+ /sbin/initqueue --settled --onetime --unique /sbin/dmsquash-live-root "${root#live:}"
+ fi
+ ;;
+esac
diff --git a/modules.d/90dmsquash-live/dmsquash-live-root.sh b/modules.d/90dmsquash-live/dmsquash-live-root.sh
new file mode 100755
index 0000000..e808339
--- /dev/null
+++ b/modules.d/90dmsquash-live/dmsquash-live-root.sh
@@ -0,0 +1,432 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+type det_fs > /dev/null 2>&1 || . /lib/fs-lib.sh
+
+command -v unpack_archive > /dev/null || . /lib/img-lib.sh
+
+PATH=/usr/sbin:/usr/bin:/sbin:/bin
+
+if getargbool 0 rd.live.debug -n -y rdlivedebug; then
+ exec > /tmp/liveroot.$$.out
+ exec 2>> /tmp/liveroot.$$.out
+ set -x
+fi
+
+[ -z "$1" ] && exit 1
+livedev="$1"
+
+# parse various live image specific options that make sense to be
+# specified as their own things
+live_dir=$(getarg rd.live.dir -d live_dir)
+[ -z "$live_dir" ] && live_dir="LiveOS"
+squash_image=$(getarg rd.live.squashimg)
+[ -z "$squash_image" ] && squash_image="squashfs.img"
+
+getargbool 0 rd.live.ram -d -y live_ram && live_ram="yes"
+getargbool 0 rd.live.overlay.reset -d -y reset_overlay && reset_overlay="yes"
+getargbool 0 rd.live.overlay.readonly -d -y readonly_overlay && readonly_overlay="--readonly" || readonly_overlay=""
+overlay=$(getarg rd.live.overlay -d overlay)
+getargbool 0 rd.writable.fsimg -d -y writable_fsimg && writable_fsimg="yes"
+overlay_size=$(getarg rd.live.overlay.size=)
+[ -z "$overlay_size" ] && overlay_size=32768
+
+getargbool 0 rd.live.overlay.thin && thin_snapshot="yes"
+getargbool 0 rd.live.overlay.overlayfs && overlayfs="yes"
+
+# Take a path to a disk label and return the parent disk if it is a partition
+# Otherwise returns the original path
+get_check_dev() {
+ local _udevinfo
+ dev_path="$(udevadm info -q path --name "$1")"
+ _udevinfo="$(udevadm info -q property --path "${dev_path}")"
+ strstr "$_udevinfo" "DEVTYPE=partition" || {
+ echo "$1"
+ return
+ }
+ parent="${dev_path%/*}"
+ _udevinfo="$(udevadm info -q property --path "${parent}")"
+ strstr "$_udevinfo" "DEVTYPE=disk" || {
+ echo "$1"
+ return
+ }
+ strstr "$_udevinfo" "ID_FS_TYPE=iso9660" || {
+ echo "$1"
+ return
+ }
+
+ # Return the name of the parent disk device
+ echo "$_udevinfo" | grep "DEVNAME=" | sed 's/DEVNAME=//'
+}
+
+# Find the right device to run check on
+check_dev=$(get_check_dev "$livedev")
+# CD/DVD media check
+[ -b "$check_dev" ] && fs=$(det_fs "$check_dev")
+if [ "$fs" = "iso9660" -o "$fs" = "udf" ]; then
+ check="yes"
+fi
+getarg rd.live.check -d check || check=""
+if [ -n "$check" ]; then
+ type plymouth > /dev/null 2>&1 && plymouth --hide-splash
+ if [ -n "$DRACUT_SYSTEMD" ]; then
+ p=$(dev_unit_name "$check_dev")
+ systemctl start checkisomd5@"${p}".service
+ else
+ checkisomd5 --verbose "$check_dev"
+ fi
+ if [ $? -eq 1 ]; then
+ die "CD check failed!"
+ exit 1
+ fi
+ type plymouth > /dev/null 2>&1 && plymouth --show-splash
+fi
+
+ln -s "$livedev" /run/initramfs/livedev
+
+# determine filesystem type for a filesystem image
+det_img_fs() {
+ udevadm settle >&2
+ blkid -s TYPE -u noraid -o value "$1"
+}
+
+load_fstype squashfs
+CMDLINE=$(getcmdline)
+for arg in $CMDLINE; do
+ case $arg in
+ ro | rw) liverw=$arg ;;
+ esac
+done
+
+# mount the backing of the live image first
+mkdir -m 0755 -p /run/initramfs/live
+if [ -f "$livedev" ]; then
+ # no mount needed - we've already got the LiveOS image in initramfs
+ # check filesystem type and handle accordingly
+ fstype=$(det_img_fs "$livedev")
+ case $fstype in
+ squashfs) SQUASHED=$livedev ;;
+ auto) die "cannot mount live image (unknown filesystem type)" ;;
+ *) FSIMG=$livedev ;;
+ esac
+ [ -e /sys/fs/"$fstype" ] || modprobe "$fstype"
+else
+ livedev_fstype=$(det_fs "$livedev")
+ if [ "$livedev_fstype" = "squashfs" ]; then
+ # no mount needed - we've already got the LiveOS image in $livedev
+ SQUASHED=$livedev
+ elif [ "$livedev_fstype" != "ntfs" ]; then
+ if ! mount -n -t "$livedev_fstype" -o "${liverw:-ro}" "$livedev" /run/initramfs/live; then
+ die "Failed to mount block device of live image"
+ exit 1
+ fi
+ else
+ [ -x "/sbin/mount-ntfs-3g" ] && /sbin/mount-ntfs-3g -o "${liverw:-ro}" "$livedev" /run/initramfs/live
+ fi
+fi
+
+# overlay setup helper function
+do_live_overlay() {
+ # create a sparse file for the overlay
+ # overlay: if non-ram overlay searching is desired, do it,
+ # otherwise, create traditional overlay in ram
+
+ l=$(blkid -s LABEL -o value "$livedev") || l=""
+ u=$(blkid -s UUID -o value "$livedev") || u=""
+
+ if [ -z "$overlay" ]; then
+ pathspec="/${live_dir}/overlay-$l-$u"
+ elif strstr "$overlay" ":"; then
+ # pathspec specified, extract
+ pathspec=${overlay##*:}
+ fi
+
+ if [ -z "$pathspec" -o "$pathspec" = "auto" ]; then
+ pathspec="/${live_dir}/overlay-$l-$u"
+ fi
+ devspec=${overlay%%:*}
+
+ # need to know where to look for the overlay
+ if [ -z "$setup" -a -n "$devspec" -a -n "$pathspec" -a -n "$overlay" ]; then
+ mkdir -m 0755 -p /run/initramfs/overlayfs
+ if ismounted "$devspec"; then
+ devmnt=$(findmnt -e -v -n -o 'TARGET' --source "$devspec")
+ # We need $devspec writable for overlay storage
+ mount -o remount,rw "$devspec"
+ mount --bind "$devmnt" /run/initramfs/overlayfs
+ else
+ mount -n -t auto "$devspec" /run/initramfs/overlayfs || :
+ fi
+ if [ -f /run/initramfs/overlayfs$pathspec -a -w /run/initramfs/overlayfs$pathspec ]; then
+ OVERLAY_LOOPDEV=$(losetup -f --show ${readonly_overlay:+-r} /run/initramfs/overlayfs$pathspec)
+ over=$OVERLAY_LOOPDEV
+ umount -l /run/initramfs/overlayfs || :
+ oltype=$(det_img_fs "$OVERLAY_LOOPDEV")
+ if [ -z "$oltype" ] || [ "$oltype" = DM_snapshot_cow ]; then
+ if [ -n "$reset_overlay" ]; then
+ info "Resetting the Device-mapper overlay."
+ dd if=/dev/zero of="$OVERLAY_LOOPDEV" bs=64k count=1 conv=fsync 2> /dev/null
+ fi
+ if [ -n "$overlayfs" ]; then
+ unset -v overlayfs
+ [ -n "$DRACUT_SYSTEMD" ] && reloadsysrootmountunit=":>/xor_overlayfs;"
+ fi
+ setup="yes"
+ else
+ mount -n -t "$oltype" ${readonly_overlay:+-r} "$OVERLAY_LOOPDEV" /run/initramfs/overlayfs
+ if [ -d /run/initramfs/overlayfs/overlayfs ] \
+ && [ -d /run/initramfs/overlayfs/ovlwork ]; then
+ ln -s /run/initramfs/overlayfs/overlayfs /run/overlayfs${readonly_overlay:+-r}
+ ln -s /run/initramfs/overlayfs/ovlwork /run/ovlwork${readonly_overlay:+-r}
+ if [ -z "$overlayfs" ] && [ -n "$DRACUT_SYSTEMD" ]; then
+ reloadsysrootmountunit=":>/xor_overlayfs;"
+ fi
+ overlayfs="required"
+ setup="yes"
+ fi
+ fi
+ elif [ -d /run/initramfs/overlayfs$pathspec ] \
+ && [ -d /run/initramfs/overlayfs$pathspec/../ovlwork ]; then
+ ln -s /run/initramfs/overlayfs$pathspec /run/overlayfs${readonly_overlay:+-r}
+ ln -s /run/initramfs/overlayfs$pathspec/../ovlwork /run/ovlwork${readonly_overlay:+-r}
+ if [ -z "$overlayfs" ] && [ -n "$DRACUT_SYSTEMD" ]; then
+ reloadsysrootmountunit=":>/xor_overlayfs;"
+ fi
+ overlayfs="required"
+ setup="yes"
+ fi
+ fi
+ if [ -n "$overlayfs" ]; then
+ if ! load_fstype overlay; then
+ if [ "$overlayfs" = required ]; then
+ die "OverlayFS is required but not available."
+ exit 1
+ fi
+ [ -n "$DRACUT_SYSTEMD" ] && reloadsysrootmountunit=":>/xor_overlayfs;"
+ m='OverlayFS is not available; using temporary Device-mapper overlay.'
+ info "$m"
+ unset -v overlayfs setup
+ fi
+ fi
+
+ if [ -z "$setup" -o -n "$readonly_overlay" ]; then
+ if [ -n "$setup" ]; then
+ warn "Using temporary overlay."
+ elif [ -n "$devspec" -a -n "$pathspec" ]; then
+ [ -z "$m" ] \
+ && m=' Unable to find a persistent overlay; using a temporary one.'
+ m="$m"'
+ All root filesystem changes will be lost on shutdown.
+ Press [Enter] to continue.'
+ printf "\n\n\n\n%s\n\n\n" "${m}" > /dev/kmsg
+ if [ -n "$DRACUT_SYSTEMD" ]; then
+ if type plymouth > /dev/null 2>&1 && plymouth --ping; then
+ if getargbool 0 rhgb || getargbool 0 splash; then
+ m='>>>
+>>>
+>>>
+
+
+'"$m"
+ m="${m%n.*}"'n.
+
+
+<<<
+<<<
+<<<'
+ plymouth display-message --text="${m}"
+ else
+ plymouth ask-question --prompt="${m}" --command=true
+ fi
+ else
+ m=">>>$(printf '%s' "$m" | tr -d '\n') <<<"
+ systemd-ask-password --timeout=0 "${m}"
+ fi
+ else
+ type plymouth > /dev/null 2>&1 && plymouth --ping && plymouth --quit
+ printf '\n\n%s' "$m"
+ read -r _
+ fi
+ fi
+ if [ -n "$overlayfs" ]; then
+ if [ -n "$readonly_overlay" ] && ! [ -h /run/overlayfs-r ]; then
+ info "No persistent overlay found."
+ unset -v readonly_overlay
+ [ -n "$DRACUT_SYSTEMD" ] && reloadsysrootmountunit="${reloadsysrootmountunit}:>/xor_readonly;"
+ fi
+ else
+ dd if=/dev/null of=/overlay bs=1024 count=1 seek=$((overlay_size * 1024)) 2> /dev/null
+ if [ -n "$setup" -a -n "$readonly_overlay" ]; then
+ RO_OVERLAY_LOOPDEV=$(losetup -f --show /overlay)
+ over=$RO_OVERLAY_LOOPDEV
+ else
+ OVERLAY_LOOPDEV=$(losetup -f --show /overlay)
+ over=$OVERLAY_LOOPDEV
+ fi
+ fi
+ fi
+
+ # set up the snapshot
+ if [ -z "$overlayfs" ]; then
+ if [ -n "$readonly_overlay" ] && [ -n "$OVERLAY_LOOPDEV" ]; then
+ echo 0 "$sz" snapshot "$BASE_LOOPDEV" "$OVERLAY_LOOPDEV" P 8 | dmsetup create --readonly live-ro
+ base="/dev/mapper/live-ro"
+ else
+ base=$BASE_LOOPDEV
+ fi
+ fi
+
+ if [ -n "$thin_snapshot" ]; then
+ modprobe dm_thin_pool
+ mkdir -m 0755 -p /run/initramfs/thin-overlay
+
+ # In block units (512b)
+ thin_data_sz=$((overlay_size * 1024 * 1024 / 512))
+ thin_meta_sz=$((thin_data_sz / 10))
+
+ # It is important to have the backing file on a tmpfs
+ # this is needed to let the loopdevice support TRIM
+ dd if=/dev/null of=/run/initramfs/thin-overlay/meta bs=1b count=1 seek=$((thin_meta_sz)) 2> /dev/null
+ dd if=/dev/null of=/run/initramfs/thin-overlay/data bs=1b count=1 seek=$((thin_data_sz)) 2> /dev/null
+
+ THIN_META_LOOPDEV=$(losetup --show -f /run/initramfs/thin-overlay/meta)
+ THIN_DATA_LOOPDEV=$(losetup --show -f /run/initramfs/thin-overlay/data)
+
+ echo 0 $thin_data_sz thin-pool "$THIN_META_LOOPDEV" "$THIN_DATA_LOOPDEV" 1024 1024 | dmsetup create live-overlay-pool
+ dmsetup message /dev/mapper/live-overlay-pool 0 "create_thin 0"
+
+ # Create a snapshot of the base image
+ echo 0 "$sz" thin /dev/mapper/live-overlay-pool 0 "$base" | dmsetup create live-rw
+ elif [ -z "$overlayfs" ]; then
+ echo 0 "$sz" snapshot "$base" "$over" PO 8 | dmsetup create live-rw
+ fi
+
+ # Create a device for the ro base of overlaid file systems.
+ if [ -z "$overlayfs" ]; then
+ echo 0 "$sz" linear "$BASE_LOOPDEV" 0 | dmsetup create --readonly live-base
+ fi
+ ln -s "$BASE_LOOPDEV" /dev/live-base
+}
+# end do_live_overlay()
+
+# we might have an embedded fs image on squashfs (compressed live)
+if [ -e /run/initramfs/live/${live_dir}/${squash_image} ]; then
+ SQUASHED="/run/initramfs/live/${live_dir}/${squash_image}"
+fi
+if [ -e "$SQUASHED" ]; then
+ if [ -n "$live_ram" ]; then
+ imgsize=$(($(stat -c %s -- $SQUASHED) / (1024 * 1024)))
+ check_live_ram $imgsize
+ echo 'Copying live image to RAM...' > /dev/kmsg
+ echo ' (this may take a minute)' > /dev/kmsg
+ dd if=$SQUASHED of=/run/initramfs/squashed.img bs=512 2> /dev/null
+ echo 'Done copying live image to RAM.' > /dev/kmsg
+ SQUASHED="/run/initramfs/squashed.img"
+ fi
+
+ SQUASHED_LOOPDEV=$(losetup -f)
+ losetup -r "$SQUASHED_LOOPDEV" $SQUASHED
+ mkdir -m 0755 -p /run/initramfs/squashfs
+ mount -n -t squashfs -o ro "$SQUASHED_LOOPDEV" /run/initramfs/squashfs
+
+ if [ -d /run/initramfs/squashfs/LiveOS ]; then
+ if [ -f /run/initramfs/squashfs/LiveOS/rootfs.img ]; then
+ FSIMG="/run/initramfs/squashfs/LiveOS/rootfs.img"
+ elif [ -f /run/initramfs/squashfs/LiveOS/ext3fs.img ]; then
+ FSIMG="/run/initramfs/squashfs/LiveOS/ext3fs.img"
+ fi
+ elif [ -d /run/initramfs/squashfs/proc ]; then
+ FSIMG=$SQUASHED
+ if [ -z "$overlayfs" ] && [ -n "$DRACUT_SYSTEMD" ]; then
+ reloadsysrootmountunit=":>/xor_overlayfs;"
+ fi
+ overlayfs="required"
+ else
+ die "Failed to find a root filesystem in $SQUASHED."
+ exit 1
+ fi
+else
+ # we might have an embedded fs image to use as rootfs (uncompressed live)
+ if [ -e /run/initramfs/live/${live_dir}/rootfs.img ]; then
+ FSIMG="/run/initramfs/live/${live_dir}/rootfs.img"
+ elif [ -e /run/initramfs/live/${live_dir}/ext3fs.img ]; then
+ FSIMG="/run/initramfs/live/${live_dir}/ext3fs.img"
+ fi
+ if [ -n "$live_ram" ]; then
+ echo 'Copying live image to RAM...' > /dev/kmsg
+ echo ' (this may take a minute or so)' > /dev/kmsg
+ dd if=$FSIMG of=/run/initramfs/rootfs.img bs=512 2> /dev/null
+ echo 'Done copying live image to RAM.' > /dev/kmsg
+ FSIMG='/run/initramfs/rootfs.img'
+ fi
+fi
+
+if [ -n "$FSIMG" ]; then
+ if [ -n "$writable_fsimg" ]; then
+ # mount the provided filesystem read/write
+ echo "Unpacking live filesystem (may take some time)" > /dev/kmsg
+ mkdir -m 0755 -p /run/initramfs/fsimg/
+ if [ -n "$SQUASHED" ]; then
+ cp -v $FSIMG /run/initramfs/fsimg/rootfs.img
+ else
+ unpack_archive $FSIMG /run/initramfs/fsimg/
+ fi
+ FSIMG=/run/initramfs/fsimg/rootfs.img
+ fi
+ # For writable DM images...
+ readonly_base=1
+ if [ -z "$SQUASHED" -a -n "$live_ram" -a -z "$overlayfs" ] \
+ || [ -n "$writable_fsimg" ] \
+ || [ "$overlay" = none -o "$overlay" = None -o "$overlay" = NONE ]; then
+ if [ -z "$readonly_overlay" ]; then
+ unset readonly_base
+ setup=rw
+ else
+ setup=yes
+ fi
+ fi
+ if [ "$FSIMG" = "$SQUASHED" ]; then
+ BASE_LOOPDEV=$SQUASHED_LOOPDEV
+ else
+ BASE_LOOPDEV=$(losetup -f --show ${readonly_base:+-r} $FSIMG)
+ sz=$(blockdev --getsz "$BASE_LOOPDEV")
+ fi
+ if [ "$setup" = rw ]; then
+ echo 0 "$sz" linear "$BASE_LOOPDEV" 0 | dmsetup create live-rw
+ else
+ # Add a DM snapshot or OverlayFS for writes.
+ do_live_overlay
+ fi
+fi
+
+if [ -n "$reloadsysrootmountunit" ]; then
+ eval "$reloadsysrootmountunit"
+ systemctl daemon-reload
+fi
+
+ROOTFLAGS="$(getarg rootflags)"
+
+if [ "$overlayfs" = required ]; then
+ echo "rd.live.overlay.overlayfs=1" > /etc/cmdline.d/dmsquash-need-overlay.conf
+fi
+
+if [ -n "$overlayfs" ]; then
+ if [ -n "$FSIMG" ]; then
+ mkdir -m 0755 -p /run/rootfsbase
+ mount -r $FSIMG /run/rootfsbase
+ else
+ ln -sf /run/initramfs/live /run/rootfsbase
+ fi
+else
+ if [ -z "$DRACUT_SYSTEMD" ]; then
+ [ -n "$ROOTFLAGS" ] && ROOTFLAGS="-o $ROOTFLAGS"
+ printf 'mount %s /dev/mapper/live-rw %s\n' "$ROOTFLAGS" "$NEWROOT" > "$hookdir"/mount/01-$$-live.sh
+ fi
+fi
+[ -e "$SQUASHED" ] && umount -l /run/initramfs/squashfs
+
+ln -s null /dev/root
+
+need_shutdown
+
+exit 0
diff --git a/modules.d/90dmsquash-live/dmsquash-liveiso-genrules.sh b/modules.d/90dmsquash-live/dmsquash-liveiso-genrules.sh
new file mode 100755
index 0000000..a5810f7
--- /dev/null
+++ b/modules.d/90dmsquash-live/dmsquash-liveiso-genrules.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+if [ "${root%%:*}" = "liveiso" ]; then
+ {
+ # shellcheck disable=SC2016
+ printf 'KERNEL=="loop-control", RUN+="/sbin/initqueue --settled --onetime --unique /sbin/dmsquash-live-root `/sbin/losetup -f --show %s`"\n' \
+ "${root#liveiso:}"
+ } >> /etc/udev/rules.d/99-liveiso-mount.rules
+fi
diff --git a/modules.d/90dmsquash-live/iso-scan.sh b/modules.d/90dmsquash-live/iso-scan.sh
new file mode 100755
index 0000000..fa06b33
--- /dev/null
+++ b/modules.d/90dmsquash-live/iso-scan.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+PATH=/usr/sbin:/usr/bin:/sbin:/bin
+
+isofile=$1
+
+[ -z "$isofile" ] && exit 1
+
+ismounted "/run/initramfs/isoscan" && exit 0
+
+mkdir -p "/run/initramfs/isoscan"
+
+do_iso_scan() {
+ local _name
+ local dev
+ for dev in /dev/disk/by-uuid/*; do
+ _name=$(dev_unit_name "$dev")
+ [ -e /tmp/isoscan-"${_name}" ] && continue
+ : > /tmp/isoscan-"${_name}"
+ mount -t auto -o ro "$dev" "/run/initramfs/isoscan" || continue
+ if [ -f "/run/initramfs/isoscan/$isofile" ]; then
+ losetup -f "/run/initramfs/isoscan/$isofile"
+ udevadm trigger --action=add > /dev/null 2>&1
+ ln -s "$dev" /run/initramfs/isoscandev
+ rm -f -- "$job"
+ exit 0
+ else
+ umount "/run/initramfs/isoscan"
+ fi
+ done
+}
+
+do_iso_scan
+
+rmdir "/run/initramfs/isoscan"
+exit 1
diff --git a/modules.d/90dmsquash-live/module-setup.sh b/modules.d/90dmsquash-live/module-setup.sh
new file mode 100755
index 0000000..b905e3d
--- /dev/null
+++ b/modules.d/90dmsquash-live/module-setup.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ # a live host-only image doesn't really make a lot of sense
+ [[ $hostonly ]] && return 1
+ return 255
+}
+
+# called by dracut
+depends() {
+ # if dmsetup is not installed, then we cannot support fedora/red hat
+ # style live images
+ echo dm rootfs-block img-lib overlayfs
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ instmods squashfs loop iso9660
+}
+
+# called by dracut
+install() {
+ inst_multiple umount dmsetup blkid dd losetup blockdev find rmdir grep
+ inst_multiple -o checkisomd5
+ inst_hook cmdline 30 "$moddir/parse-dmsquash-live.sh"
+ inst_hook cmdline 31 "$moddir/parse-iso-scan.sh"
+ inst_hook pre-udev 30 "$moddir/dmsquash-live-genrules.sh"
+ inst_hook pre-udev 30 "$moddir/dmsquash-liveiso-genrules.sh"
+ inst_hook pre-pivot 20 "$moddir/apply-live-updates.sh"
+ inst_script "$moddir/dmsquash-live-root.sh" "/sbin/dmsquash-live-root"
+ inst_script "$moddir/iso-scan.sh" "/sbin/iso-scan"
+ if dracut_module_included "systemd-initrd"; then
+ inst_script "$moddir/dmsquash-generator.sh" "$systemdutildir"/system-generators/dracut-dmsquash-generator
+ inst_simple "$moddir/checkisomd5@.service" "/etc/systemd/system/checkisomd5@.service"
+ fi
+ dracut_need_initqueue
+}
diff --git a/modules.d/90dmsquash-live/parse-dmsquash-live.sh b/modules.d/90dmsquash-live/parse-dmsquash-live.sh
new file mode 100755
index 0000000..de910b3
--- /dev/null
+++ b/modules.d/90dmsquash-live/parse-dmsquash-live.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+# live images are specified with
+# root=live:backingdev
+
+[ -z "$root" ] && root=$(getarg root=)
+
+# support legacy syntax of passing liveimg and then just the base root
+if getargbool 0 rd.live.image -d -y liveimg; then
+ liveroot="live:$root"
+fi
+
+if [ "${root%%:*}" = "live" ]; then
+ liveroot=$root
+fi
+
+[ "${liveroot%%:*}" = "live" ] || return 1
+
+modprobe -q loop
+
+case "$liveroot" in
+ live:LABEL=* | LABEL=* | live:UUID=* | UUID=* | live:PARTUUID=* | PARTUUID=* | live:PARTLABEL=* | PARTLABEL=*)
+ root="live:$(label_uuid_to_dev "${root#live:}")"
+ rootok=1
+ ;;
+ live:CDLABEL=* | CDLABEL=*)
+ root="${root#live:}"
+ root="$(echo "$root" | sed 's,/,\\x2f,g;s, ,\\x20,g')"
+ root="live:/dev/disk/by-label/${root#CDLABEL=}"
+ rootok=1
+ ;;
+ live:/*.[Ii][Ss][Oo] | /*.[Ii][Ss][Oo])
+ root="${root#live:}"
+ root="liveiso:${root}"
+ rootok=1
+ ;;
+ live:/dev/*)
+ root="live:${root#live:}"
+ rootok=1
+ ;;
+ live:/*.[Ii][Mm][Gg] | /*.[Ii][Mm][Gg])
+ [ -f "${root#live:}" ] && rootok=1
+ ;;
+ live:nfs*)
+ rootok=1
+ ;;
+esac
+
+[ "$rootok" = "1" ] || return 1
+
+info "root was $liveroot, is now $root"
+
+# make sure that init doesn't complain
+[ -z "$root" ] && root="live"
+
+wait_for_dev -n /dev/root
+
+return 0
diff --git a/modules.d/90dmsquash-live/parse-iso-scan.sh b/modules.d/90dmsquash-live/parse-iso-scan.sh
new file mode 100755
index 0000000..1dd2d37
--- /dev/null
+++ b/modules.d/90dmsquash-live/parse-iso-scan.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+# live images are specified with
+# root=live:backingdev
+
+isofile=$(getarg iso-scan/filename)
+
+if [ -n "$isofile" ]; then
+ /sbin/initqueue --settled --unique /sbin/iso-scan "$isofile"
+fi
diff --git a/modules.d/90kernel-modules-extra/module-setup.sh b/modules.d/90kernel-modules-extra/module-setup.sh
new file mode 100755
index 0000000..85e2e0a
--- /dev/null
+++ b/modules.d/90kernel-modules-extra/module-setup.sh
@@ -0,0 +1,186 @@
+#!/bin/bash
+
+# called by dracut
+#
+# Parses depmod configuration and calls instmods for out-of-tree kernel
+# modules found. Specifically, kernel modules inside directories that
+# come from the following places are included (if these kernel modules
+# are present in modules.dep):
+# - "search" configuration option;
+# - "override" configuration option (matching an exact file name constructed
+# by concatenating the provided directory and the kernel module name);
+# - "external" configuration option (if "external" is a part of "search"
+# configuration).
+# (See depmod.d(5) for details.)
+#
+# This module has the following variables available for configuration:
+# - "depmod_modules_dep" - Path to the modules.dep file
+# ("$srcmods/modules.dep" by default);
+# - "depmod_module_dir" - Directory containing kernel modules ("$srcmods"
+# by default);
+# - "depmod_configs" - array of depmod configuration paths to parse
+# (as supplied to depmod -C, ("/run/depmod.d/"
+# "/etc/depmod.d/" "/lib/depmod.d/") by default).
+installkernel() {
+ : "${depmod_modules_dep:=$srcmods/modules.dep}"
+ : "${depmod_module_dir:=$srcmods}"
+
+ [[ -f ${depmod_modules_dep} ]] || return 0
+
+ # Message printers with custom prefix
+ local mod_name="kernel-modules-extra"
+ prinfo() { dinfo " ${mod_name}: $*"; }
+ prdebug() { ddebug " ${mod_name}: $*"; }
+
+ # Escape a string for usage as a part of extended regular expression.
+ # $1 - string to escape
+ re_escape() {
+ printf "%s" "$1" | sed 's/\([.+?^$\/\\|()\[]\|\]\)/\\\0/'
+ }
+
+ local cfg
+ local cfgs=()
+ local search_list=""
+ local overrides=()
+ local external_dirs=()
+ local e f
+
+ ## Gathering and sorting configuration file list
+
+ [ -n "${depmod_configs[*]-}" ] \
+ || depmod_configs=(/run/depmod.d /etc/depmod.d /lib/depmod.d)
+
+ for cfg in "${depmod_configs[@]}"; do
+ [ -e "$cfg" ] || {
+ prdebug "configuration source \"$cfg\" does not exist"
+ continue
+ }
+
+ # '/' is used as a separator between configuration name and
+ # configuration path
+ if [ -d "$cfg" ]; then
+ for f in "$cfg/"*.conf; do
+ [[ -e $f && ! -d $f ]] || {
+ prdebug "configuration source" \
+ "\"$cfg\" is ignored" \
+ "(directory or doesn't exist)"
+ continue
+ }
+ cfgs+=("${f##*/}/$f")
+ done
+ else
+ cfgs+=("${cfg##*/}/$cfg")
+ fi
+ done
+
+ if ((${#cfgs[@]} > 0)); then
+ mapfile -t cfgs < <(printf '%s\n' "${cfgs[@]}" | LANG=C sort -u -k1,1 -t '/' | cut -f 2- -d '/')
+ fi
+
+ ## Parse configurations
+
+ for cfg in "${cfgs[@]}"; do
+ prdebug "parsing configuration file \"$cfg\""
+
+ local k v mod kverpat path
+ while read -r k v; do
+ case "$k" in
+ search)
+ search_list="$search_list $v"
+ prdebug "$cfg: added \"$v\" to the list of" \
+ "search directories"
+ ;;
+ override) # module_name kver_pattern dir
+ read -r mod kverpat path <<< "$v"
+
+ if [[ ! $mod || ! $kverpat || ! $path ]]; then
+ prinfo "$cfg: ignoring incorrect" \
+ "override option: \"$k $v\""
+ continue
+ fi
+
+ if [[ '*' == "$kverpat" ]] \
+ || [[ $kernel =~ $kverpat ]]; then
+ overrides+=("${path}/${mod}")
+
+ prdebug "$cfg: added override" \
+ "\"${path}/${mod}\""
+ else
+ prdebug "$cfg: override \"$v\" is" \
+ "ignored since \"$kverpat\"" \
+ "doesn't match \"$kernel\""
+ fi
+ ;;
+ external) # kverpat dir
+ read -r kverpat path <<< "$v"
+
+ if [[ ! $kverpat || ! $path ]]; then
+ prinfo "$cfg: ignoring incorrect" \
+ "external option: \"$k $v\""
+ continue
+ fi
+
+ if [[ '*' == "$kverpat" ]] \
+ || [[ $kernel =~ $kverpat ]]; then
+ external_dirs+=("$path")
+
+ prdebug "$cfg: added external" \
+ "directory \"$path\""
+ else
+ prdebug "$cfg: external directory" \
+ "\"$path\" is ignored since" \
+ "\"$kverpat\" doesn't match " \
+ "\"$kernel\""
+ fi
+ ;;
+ '#'* | '') # comments and empty strings
+ ;;
+ include | make_map_files) # ignored by depmod
+ ;;
+ *)
+ prinfo "$cfg: unknown depmod configuration" \
+ "option \"$k $v\""
+ ;;
+ esac
+ done < "$cfg"
+ done
+
+ # "updates built-in" is the default search list
+ : "${search_list:=updates}"
+
+ ## Build a list of regular expressions for grepping modules.dep
+
+ local pathlist=()
+ for f in "${overrides[@]}"; do
+ pathlist+=("^$(re_escape "$f")")
+ done
+
+ for f in $(printf "%s" "$search_list"); do
+ # Ignoring builtin modules
+ [[ $f == "built-in" ]] && continue
+
+ if [[ $f == "external" ]]; then
+ for e in "${external_dirs[@]}"; do
+ pathlist+=("$(re_escape "${e%/}")/[^:]+")
+ done
+ fi
+
+ pathlist+=("$(re_escape "${f%/}")/[^:]+")
+ done
+
+ ## Filter modules.dep, canonicalise the resulting filenames and supply
+ ## them to instmods.
+
+ ((${#pathlist[@]} > 0)) || return 0
+
+ printf "^%s\.ko(\.gz|\.bz2|\.xz|\.zst)?:\n" "${pathlist[@]}" \
+ | (LANG=C grep -E -o -f - -- "$depmod_modules_dep" || exit 0) \
+ | tr -d ':' \
+ | (
+ cd "$depmod_module_dir" || exit
+ xargs -r realpath -se --
+ ) \
+ | instmods || return 1
+
+ return 0
+}
diff --git a/modules.d/90kernel-modules/insmodpost.sh b/modules.d/90kernel-modules/insmodpost.sh
new file mode 100755
index 0000000..a7ab05b
--- /dev/null
+++ b/modules.d/90kernel-modules/insmodpost.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+. /lib/dracut-lib.sh
+
+for modlist in $(getargs rd.driver.post -d rdinsmodpost=); do
+ (
+ IFS=,
+ for m in $modlist; do
+ modprobe "$m"
+ done
+ )
+done
diff --git a/modules.d/90kernel-modules/module-setup.sh b/modules.d/90kernel-modules/module-setup.sh
new file mode 100755
index 0000000..e217512
--- /dev/null
+++ b/modules.d/90kernel-modules/module-setup.sh
@@ -0,0 +1,154 @@
+#!/bin/bash
+
+# called by dracut
+installkernel() {
+ local _blockfuncs='ahci_platform_get_resources|ata_scsi_ioctl|scsi_add_host|blk_cleanup_queue|register_mtd_blktrans|scsi_esp_register|register_virtio_device|usb_stor_disconnect|mmc_add_host|sdhci_add_host|scsi_add_host_with_dma|blk_mq_alloc_disk|blk_mq_alloc_request|blk_mq_destroy_queue|blk_cleanup_disk'
+ local -A _hostonly_drvs
+
+ record_block_dev_drv() {
+
+ for _mod in $(get_dev_module /dev/block/"$1"); do
+ _hostonly_drvs["$_mod"]="$_mod"
+ done
+
+ for _mod in $(get_blockdev_drv_through_sys "/sys/dev/block/$1"); do
+ _hostonly_drvs["$_mod"]="$_mod"
+ done
+
+ ((${#_hostonly_drvs[@]} > 0)) && return 0
+ return 1
+ }
+
+ install_block_modules_strict() {
+ hostonly='' instmods "${_hostonly_drvs[@]}"
+ }
+
+ install_block_modules() {
+ instmods \
+ scsi_dh_rdac scsi_dh_emc scsi_dh_alua \
+ =drivers/usb/storage \
+ =ide nvme vmd \
+ virtio_blk virtio_scsi \
+ =drivers/ufs
+
+ dracut_instmods -o -s "${_blockfuncs}" "=drivers"
+ }
+
+ if [[ -z $drivers ]]; then
+ hostonly='' instmods \
+ hid_generic unix
+
+ hostonly=$(optional_hostonly) instmods \
+ ehci-hcd ehci-pci ehci-platform \
+ ohci-hcd ohci-pci \
+ uhci-hcd \
+ usbhid \
+ xhci-hcd xhci-pci xhci-plat-hcd \
+ "=drivers/hid" \
+ "=drivers/tty/serial" \
+ "=drivers/input/serio" \
+ "=drivers/input/keyboard" \
+ "=drivers/pci/host" \
+ "=drivers/pci/controller" \
+ "=drivers/pinctrl" \
+ "=drivers/usb/typec" \
+ "=drivers/watchdog"
+
+ instmods \
+ yenta_socket spi_pxa2xx_platform \
+ atkbd i8042 firewire-ohci pcmcia hv-vmbus \
+ virtio virtio_ring virtio_pci pci_hyperv \
+ "=drivers/pcmcia"
+
+ if [[ ${DRACUT_ARCH:-$(uname -m)} == arm* || ${DRACUT_ARCH:-$(uname -m)} == aarch64 || ${DRACUT_ARCH:-$(uname -m)} == riscv* ]]; then
+ # arm/aarch64 specific modules
+ _blockfuncs+='|dw_mc_probe|dw_mci_pltfm_register|nvme_init_ctrl'
+ instmods \
+ "=drivers/clk" \
+ "=drivers/devfreq" \
+ "=drivers/dma" \
+ "=drivers/extcon" \
+ "=drivers/gpio" \
+ "=drivers/hwmon" \
+ "=drivers/hwspinlock" \
+ "=drivers/interconnect" \
+ "=drivers/i2c/busses" \
+ "=drivers/mailbox" \
+ "=drivers/memory" \
+ "=drivers/mfd" \
+ "=drivers/mmc/core" \
+ "=drivers/mmc/host" \
+ "=drivers/nvmem" \
+ "=drivers/phy" \
+ "=drivers/power" \
+ "=drivers/regulator" \
+ "=drivers/reset" \
+ "=drivers/rpmsg" \
+ "=drivers/rtc" \
+ "=drivers/soc" \
+ "=drivers/spi" \
+ "=drivers/usb/chipidea" \
+ "=drivers/usb/dwc2" \
+ "=drivers/usb/dwc3" \
+ "=drivers/usb/host" \
+ "=drivers/usb/isp1760" \
+ "=drivers/usb/misc" \
+ "=drivers/usb/musb" \
+ "=drivers/usb/phy" \
+ "=drivers/scsi/hisi_sas"
+ fi
+
+ awk -F: '/^\// {print $1}' "$srcmods/modules.dep" 2> /dev/null | instmods
+
+ # if not on hostonly mode, or there are hostonly block device
+ # install block drivers
+ if ! [[ $hostonly ]] \
+ || for_each_host_dev_and_slaves_all record_block_dev_drv; then
+ hostonly='' instmods sg sr_mod sd_mod scsi_dh ata_piix
+
+ if [[ $hostonly_mode == "strict" ]]; then
+ install_block_modules_strict
+ else
+ install_block_modules
+ fi
+ fi
+
+ # if not on hostonly mode, install all known filesystems,
+ # if the required list is not set via the filesystems variable
+ if ! [[ $hostonly ]]; then
+ if [[ -z $filesystems ]]; then
+ dracut_instmods -o -P ".*/(kernel/fs/nfs|kernel/fs/nfsd|kernel/fs/lockd)/.*" '=fs'
+ fi
+ elif [[ "${host_fs_types[*]}" ]]; then
+ hostonly='' instmods "${host_fs_types[@]}"
+ fi
+
+ arch=${DRACUT_ARCH:-$(uname -m)}
+
+ # We don't want to play catch up with hash and encryption algorithms.
+ # To be safe, just use the hammer and include all crypto.
+ [[ $arch == x86_64 ]] && arch=x86
+ [[ $arch == s390x ]] && arch=s390
+ [[ $arch == aarch64 ]] && arch=arm64
+ hostonly='' instmods "=crypto"
+ instmods "=arch/$arch/crypto" "=drivers/crypto"
+ fi
+
+ inst_multiple -o "$depmodd/*.conf"
+ if [[ $hostonly ]]; then
+ inst_multiple -H -o "$depmodconfdir/*.conf"
+ fi
+ :
+}
+
+# called by dracut
+install() {
+ [[ -d /lib/modprobe.d ]] && inst_multiple -o "/lib/modprobe.d/*.conf"
+ [[ -d /usr/lib/modprobe.d ]] && inst_multiple -o "/usr/lib/modprobe.d/*.conf"
+ [[ $hostonly ]] && inst_multiple -H -o /etc/modprobe.d/*.conf /etc/modprobe.conf
+ if ! dracut_module_included "systemd"; then
+ inst_hook cmdline 01 "$moddir/parse-kernel.sh"
+ fi
+ inst_simple "$moddir/insmodpost.sh" /sbin/insmodpost.sh
+ inst_multiple -o sysctl
+}
diff --git a/modules.d/90kernel-modules/parse-kernel.sh b/modules.d/90kernel-modules/parse-kernel.sh
new file mode 100755
index 0000000..d14f912
--- /dev/null
+++ b/modules.d/90kernel-modules/parse-kernel.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+_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
diff --git a/modules.d/90kernel-network-modules/module-setup.sh b/modules.d/90kernel-network-modules/module-setup.sh
new file mode 100755
index 0000000..49823ef
--- /dev/null
+++ b/modules.d/90kernel-network-modules/module-setup.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ return 255
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ # Include wired net drivers, excluding wireless
+ local _arch=${DRACUT_ARCH:-$(uname -m)}
+ local _net_symbols='eth_type_trans|register_virtio_device|usbnet_open'
+ local _unwanted_drivers='/(wireless|isdn|uwb|net/ethernet|net/phy|net/team)/'
+ local _net_drivers
+
+ if [[ $_arch == "s390" ]] || [[ $_arch == "s390x" ]]; then
+ dracut_instmods -o -P ".*${_unwanted_drivers}.*" -s "$_net_symbols" "=drivers/s390/net"
+ fi
+
+ if [[ $hostonly_mode == 'strict' ]] && [[ -n ${hostonly_nics+x} ]]; then
+ for _nic in $hostonly_nics; do
+ mapfile -t _net_drivers < <(get_dev_module /sys/class/net/"$_nic")
+ if ((${#_net_drivers[@]} == 0)); then
+ derror "--hostonly-nics contains invalid NIC '$_nic'"
+ continue
+ fi
+ hostonly="" instmods "${_net_drivers[@]}"
+ done
+ return 0
+ fi
+
+ dracut_instmods -o -P ".*${_unwanted_drivers}.*" -s "$_net_symbols" "=drivers/net"
+ #instmods() will take care of hostonly
+ instmods \
+ '=drivers/net/mdio' \
+ '=drivers/net/phy' \
+ '=drivers/net/team' \
+ '=drivers/net/ethernet' \
+ ecb arc4 bridge stp llc ipv6 bonding 8021q ipvlan macvlan af_packet virtio_net xennet
+}
+
+# called by dracut
+install() {
+ return 0
+}
diff --git a/modules.d/90livenet/fetch-liveupdate.sh b/modules.d/90livenet/fetch-liveupdate.sh
new file mode 100755
index 0000000..3ff2a9c
--- /dev/null
+++ b/modules.d/90livenet/fetch-liveupdate.sh
@@ -0,0 +1,31 @@
+#!/bin/sh
+# fetch-liveupdate - fetch an update image for dmsquash-live media.
+# this gets called by the "initqueue/online" hook for each network interface
+# that comes online.
+
+# no updates requested? we're not needed.
+[ -e /tmp/liveupdates.info ] || return 0
+
+command -v getarg > /dev/null || . /lib/dracut-lib.sh
+command -v fetch_url > /dev/null || . /lib/url-lib.sh
+command -v unpack_img > /dev/null || . /lib/img-lib.sh
+
+read -r url < /tmp/liveupdates.info
+
+info "fetching live updates from $url"
+
+if ! fetch_url "$url" /tmp/updates.img; then
+ warn "failed to fetch update image!"
+ warn "url: $url"
+ return 1
+fi
+
+if ! unpack_img /tmp/updates.img /updates.tmp.$$; then
+ warn "failed to unpack update image!"
+ warn "url: $url"
+ return 1
+fi
+
+copytree /updates.tmp.$$ /updates
+
+mv /tmp/liveupdates.info /tmp/liveupdates.done
diff --git a/modules.d/90livenet/livenet-generator.sh b/modules.d/90livenet/livenet-generator.sh
new file mode 100755
index 0000000..3e9226b
--- /dev/null
+++ b/modules.d/90livenet/livenet-generator.sh
@@ -0,0 +1,84 @@
+#!/bin/bash
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+[ -z "$root" ] && root=$(getarg root=)
+
+# support legacy syntax of passing liveimg and then just the base root
+if getargbool 0 rd.live.image -d -y liveimg; then
+ liveroot="live:$root"
+fi
+
+if [ "${root%%:*}" = "live" ]; then
+ liveroot=$root
+fi
+
+[ "${liveroot%%:*}" = "live" ] || exit 0
+
+case "$liveroot" in
+ live:nfs://* | nfs://*)
+ root="${root#live:}"
+ rootok=1
+ ;;
+ live:http://* | http://*)
+ root="${root#live:}"
+ rootok=1
+ ;;
+ live:https://* | https://*)
+ root="${root#live:}"
+ rootok=1
+ ;;
+ live:ftp://* | ftp://*)
+ root="${root#live:}"
+ rootok=1
+ ;;
+ live:torrent://* | torrent://*)
+ root="${root#live:}"
+ rootok=1
+ ;;
+ live:tftp://* | tftp://*)
+ root="${root#live:}"
+ rootok=1
+ ;;
+esac
+
+[ "$rootok" != "1" ] && exit 0
+
+GENERATOR_DIR="$2"
+[ -z "$GENERATOR_DIR" ] && exit 1
+
+[ -d "$GENERATOR_DIR" ] || mkdir -p "$GENERATOR_DIR"
+
+getargbool 0 rd.live.overlay.readonly -d -y readonly_overlay && readonly_overlay="--readonly" || readonly_overlay=""
+getargbool 0 rd.live.overlay.overlayfs && overlayfs="yes"
+[ -e /xor_overlayfs ] && xor_overlayfs="yes"
+[ -e /xor_readonly ] && xor_readonly="--readonly"
+ROOTFLAGS="$(getarg rootflags)"
+{
+ echo "[Unit]"
+ echo "Before=initrd-root-fs.target"
+ echo "[Mount]"
+ echo "Where=/sysroot"
+ if [ "$overlayfs$xor_overlayfs" = "yes" ]; then
+ echo "What=LiveOS_rootfs"
+ if [ "$readonly_overlay$xor_readonly" = "--readonly" ]; then
+ ovlfs=lowerdir=/run/overlayfs-r:/run/rootfsbase
+ else
+ ovlfs=lowerdir=/run/rootfsbase
+ fi
+ echo "Options=${ROOTFLAGS},${ovlfs},upperdir=/run/overlayfs,workdir=/run/ovlwork"
+ echo "Type=overlay"
+ _dev=LiveOS_rootfs
+ else
+ echo "What=/dev/mapper/live-rw"
+ [ -n "$ROOTFLAGS" ] && echo "Options=${ROOTFLAGS}"
+ _dev=$'dev-mapper-live\\x2drw'
+ fi
+} > "$GENERATOR_DIR"/sysroot.mount
+
+mkdir -p "$GENERATOR_DIR/$_dev.device.d"
+{
+ echo "[Unit]"
+ echo "JobTimeoutSec=3000"
+ echo "JobRunningTimeoutSec=3000"
+} > "$GENERATOR_DIR/$_dev.device.d/timeout.conf"
diff --git a/modules.d/90livenet/livenetroot.sh b/modules.d/90livenet/livenetroot.sh
new file mode 100755
index 0000000..66dd41b
--- /dev/null
+++ b/modules.d/90livenet/livenetroot.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+# livenetroot - fetch a live image from the network and run it
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+. /lib/url-lib.sh
+
+PATH=/usr/sbin:/usr/bin:/sbin:/bin
+RETRIES=${RETRIES:-100}
+SLEEP=${SLEEP:-5}
+
+[ -e /tmp/livenet.downloaded ] && exit 0
+
+# args get passed from 40network/netroot
+netroot="$2"
+liveurl="${netroot#livenet:}"
+info "fetching $liveurl"
+
+if getargbool 0 'rd.writable.fsimg'; then
+
+ imgsize=$(($(curl -sIL "$liveurl" | sed -n 's/Content-Length: *\([[:digit:]]*\).*/\1/p') / (1024 * 1024)))
+
+ check_live_ram $imgsize
+fi
+
+imgfile=
+#retry until the imgfile is populated with data or the max retries
+i=1
+while [ "$i" -le "$RETRIES" ]; do
+ imgfile=$(fetch_url "$liveurl")
+
+ # shellcheck disable=SC2181
+ if [ $? != 0 ]; then
+ warn "failed to download live image: error $?"
+ imgfile=
+ fi
+
+ if [ -n "$imgfile" -a -s "$imgfile" ]; then
+ break
+ else
+ if [ $i -ge "$RETRIES" ]; then
+ warn "failed to download live image after $i attempts."
+ exit 1
+ fi
+
+ sleep "$SLEEP"
+ fi
+
+ i=$((i + 1))
+done > /tmp/livenet.downloaded
+
+# TODO: couldn't dmsquash-live-root handle this?
+if [ "${imgfile##*.}" = "iso" ]; then
+ root=$(losetup -f)
+ losetup "$root" "$imgfile"
+else
+ root=$imgfile
+fi
+
+exec /sbin/dmsquash-live-root "$root"
diff --git a/modules.d/90livenet/module-setup.sh b/modules.d/90livenet/module-setup.sh
new file mode 100755
index 0000000..db0def5
--- /dev/null
+++ b/modules.d/90livenet/module-setup.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+# module-setup.sh for livenet
+
+# called by dracut
+check() {
+ return 255
+}
+
+# called by dracut
+depends() {
+ echo network url-lib dmsquash-live img-lib bash
+ return 0
+}
+
+# called by dracut
+install() {
+ inst_hook cmdline 29 "$moddir/parse-livenet.sh"
+ inst_hook initqueue/online 95 "$moddir/fetch-liveupdate.sh"
+ inst_script "$moddir/livenetroot.sh" "/sbin/livenetroot"
+ if dracut_module_included "systemd-initrd"; then
+ inst_script "$moddir/livenet-generator.sh" "$systemdutildir"/system-generators/dracut-livenet-generator
+ fi
+ dracut_need_initqueue
+}
diff --git a/modules.d/90livenet/parse-livenet.sh b/modules.d/90livenet/parse-livenet.sh
new file mode 100755
index 0000000..a1d14a8
--- /dev/null
+++ b/modules.d/90livenet/parse-livenet.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+# live net images - just like live images, but specified like:
+# root=live:[url-to-backing-file]
+
+[ -z "$root" ] && root=$(getarg root=)
+. /lib/url-lib.sh
+
+# live updates
+updates=$(getarg live.updates=)
+if [ -n "$updates" ]; then
+ # make sure network comes up even if we're doing a local live device
+ if [ -z "$netroot" ]; then
+ echo > /tmp/net.ifaces
+ fi
+ echo "$updates" > /tmp/liveupdates.info
+ echo '[ -e /tmp/liveupdates.done ]' > "$hookdir"/initqueue/finished/liveupdates.sh
+fi
+
+str_starts "$root" "live:" && liveurl="$root"
+str_starts "$liveurl" "live:" || return
+liveurl="${liveurl#live:}"
+
+# setting netroot to "livenet:..." makes "livenetroot" get run after ifup
+if get_url_handler "$liveurl" > /dev/null; then
+ info "livenet: root image at $liveurl"
+ netroot="livenet:$liveurl"
+ root="livenet" # quiet complaints from init
+ # shellcheck disable=SC2034
+ rootok=1
+ wait_for_dev -n /dev/root
+else
+ info "livenet: no url handler for $liveurl"
+fi
diff --git a/modules.d/90lvm/64-lvm.rules b/modules.d/90lvm/64-lvm.rules
new file mode 100644
index 0000000..1ad4911
--- /dev/null
+++ b/modules.d/90lvm/64-lvm.rules
@@ -0,0 +1,29 @@
+# hacky rules to try to activate lvm when we get new block devs...
+#
+# Copyright 2008, Red Hat, Inc.
+# Jeremy Katz <katzj@redhat.com>
+
+
+SUBSYSTEM!="block", GOTO="lvm_end"
+ACTION!="add|change", GOTO="lvm_end"
+
+# If the md device is active (indicated by array_state), then set the flag
+# LVM_MD_PV_ACTIVATED=1 indicating that the md device for the PV is ready
+# to be used. The lvm udev rule running in root will check that this flag
+# is set before it will process the md device (it wants to avoid
+# processing an md device that exists but is not yet ready to be used.)
+KERNEL=="md[0-9]*", ACTION=="change", ENV{ID_FS_TYPE}=="LVM2_member", ENV{LVM_MD_PV_ACTIVATED}!="1", TEST=="md/array_state", ENV{LVM_MD_PV_ACTIVATED}="1"
+
+# Also don't process disks that are slated to be a multipath device
+ENV{DM_MULTIPATH_DEVICE_PATH}=="1", GOTO="lvm_end"
+KERNEL=="dm-[0-9]*", ACTION=="add", GOTO="lvm_end"
+ENV{ID_FS_TYPE}!="LVM?_member", GOTO="lvm_end"
+
+PROGRAM=="/bin/sh -c 'for i in $sys/$devpath/holders/dm-[0-9]*; do [ -e $$i ] && exit 0; done; exit 1;' ", \
+ GOTO="lvm_end"
+
+RUN+="/sbin/initqueue --settled --onetime --unique /sbin/lvm_scan"
+RUN+="/sbin/initqueue --timeout --name 51-lvm_scan --onetime --unique /sbin/lvm_scan --activationmode degraded"
+RUN+="/bin/sh -c '>/tmp/.lvm_scan-%k;'"
+
+LABEL="lvm_end"
diff --git a/modules.d/90lvm/lvm_scan.sh b/modules.d/90lvm/lvm_scan.sh
new file mode 100755
index 0000000..980e449
--- /dev/null
+++ b/modules.d/90lvm/lvm_scan.sh
@@ -0,0 +1,176 @@
+#!/bin/sh
+
+# run lvm scan if udev has settled
+
+extraargs="$*"
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+VGS=$(getargs rd.lvm.vg -d rd_LVM_VG=)
+LVS=$(getargs rd.lvm.lv -d rd_LVM_LV=)
+
+# shellcheck disable=SC2174
+[ -d /etc/lvm ] || mkdir -m 0755 -p /etc/lvm
+[ -d /run/lvm ] || mkdir -m 0755 -p /run/lvm
+# build a list of devices to scan
+lvmdevs=$(
+ for f in /tmp/.lvm_scan-*; do
+ [ -e "$f" ] || continue
+ printf '%s' "${f##/tmp/.lvm_scan-} "
+ done
+)
+
+check_lvm_ver() {
+ maj=$1
+ min=$2
+ ver=$3
+ # --poll is supported since 2.2.57
+ [ "$4" -lt "$maj" ] && return 1
+ [ "$4" -gt "$maj" ] && return 0
+ [ "$5" -lt "$min" ] && return 1
+ [ "$5" -gt "$min" ] && return 0
+ [ "$6" -ge "$ver" ] && return 0
+ return 1
+}
+
+no_lvm_conf_filter() {
+ if [ ! -e /etc/lvm/lvm.conf ]; then
+ return 0
+ fi
+
+ if [ -e /run/lvm/initrd_no_filter ]; then
+ return 0
+ fi
+
+ if [ -e /run/lvm/initrd_filter ]; then
+ return 1
+ fi
+
+ if [ -e /run/lvm/initrd_global_filter ]; then
+ return 1
+ fi
+
+ # Save lvm config results in /run to avoid running
+ # lvm config commands for every PV that's scanned.
+
+ filter=$(lvm config devices/filter 2> /dev/null | grep "$filter=")
+ if [ -n "$filter" ]; then
+ printf '%s\n' "$filter" > /run/lvm/initrd_filter
+ return 1
+ fi
+
+ global_filter=$(lvm config devices/global_filter 2> /dev/null | grep "$global_filter=")
+ if [ -n "$global_filter" ]; then
+ printf '%s\n' "$global_filter" > /run/lvm/initrd_global_filter
+ return 1
+ fi
+
+ # /etc/lvm/lvm.conf exists with no filter setting
+ true > /run/lvm/initrd_no_filter
+ return 0
+}
+
+# If no lvm.conf exists, create a basic one with a global section.
+if [ ! -e /etc/lvm/lvm.conf ]; then
+ {
+ echo 'global {'
+ echo '}'
+ } > /etc/lvm/lvm.conf
+ lvmwritten=1
+fi
+
+# Save the original lvm.conf before appending a filter setting.
+if [ ! -e /etc/lvm/lvm.conf.orig ]; then
+ cp /etc/lvm/lvm.conf /etc/lvm/lvm.conf.orig
+fi
+
+# If the original lvm.conf does not contain a filter setting,
+# then generate a filter and append it to the original lvm.conf.
+# The filter is generated from the list PVs that have been seen
+# so far (each has been processed by the lvm udev rule.)
+if no_lvm_conf_filter; then
+ {
+ echo 'devices {'
+ printf ' filter = [ '
+ for dev in $lvmdevs; do
+ printf '"a|^/dev/%s$|", ' "$dev"
+ done
+ echo '"r/.*/" ]'
+ echo '}'
+ } > /etc/lvm/lvm.conf.filter
+ lvmfilter=1
+ cat /etc/lvm/lvm.conf.orig /etc/lvm/lvm.conf.filter > /etc/lvm/lvm.conf
+fi
+
+# hopefully this output format will never change, e.g.:
+# LVM version: 2.02.53(1) (2009-09-25)
+OLDIFS=$IFS
+IFS=.
+# shellcheck disable=SC2046
+set -- $(lvm version 2> /dev/null)
+IFS=$OLDIFS
+maj=${1##*:}
+min=$2
+sub=${3%% *}
+sub=${sub%%\(*}
+
+# For lvchange and vgchange use --sysinit which:
+# disables polling (--poll n)
+# ignores monitoring (--ignoremonitoring)
+# ignores locking failures (--ignorelockingfailure)
+# disables hints (--nohints)
+#
+# For lvs and vgscan:
+# disable locking (--nolocking)
+# disable hints (--nohints)
+
+activate_args="--sysinit $extraargs"
+unset extraargs
+
+export LVM_SUPPRESS_LOCKING_FAILURE_MESSAGES=1
+
+scan_args="--nolocking"
+
+check_lvm_ver 2 3 14 "$maj" "$min" "$sub" \
+ && scan_args="$scan_args --nohints"
+
+if [ -n "$LVS" ]; then
+ info "Scanning devices $lvmdevs for LVM logical volumes $LVS"
+ # shellcheck disable=SC2086
+ LVSLIST=$(lvm lvs $scan_args --noheading -o lv_full_name,segtype $LVS)
+ info "$LVSLIST"
+
+ # Only attempt to activate an LV if it appears in the lvs output.
+ for LV in $LVS; do
+ if strstr "$LVSLIST" "$LV"; then
+ # This lvchange is expected to fail if all PVs used by
+ # the LV are not yet present. Premature/failed lvchange
+ # could be avoided by reporting if an LV is complete
+ # from the lvs command above and skipping this lvchange
+ # if the LV is not lised as complete.
+ # shellcheck disable=SC2086
+ lvm lvchange --yes -K -ay $activate_args "$LV" 2>&1 | vinfo
+ fi
+ done
+fi
+
+if [ -z "$LVS" ] || [ -n "$VGS" ]; then
+ info "Scanning devices $lvmdevs for LVM volume groups $VGS"
+ # shellcheck disable=SC2086
+ lvm vgscan $scan_args 2>&1 | vinfo
+ # shellcheck disable=SC2086
+ lvm vgchange -ay $activate_args $VGS 2>&1 | vinfo
+fi
+
+if [ "$lvmwritten" ]; then
+ rm -f -- /etc/lvm/lvm.conf
+elif [ "$lvmfilter" ]; then
+ # revert filter that was appended to existing lvm.conf
+ cp /etc/lvm/lvm.conf.orig /etc/lvm/lvm.conf
+ rm -f -- /etc/lvm/lvm.conf.filter
+fi
+unset lvmwritten
+unset lvmfilter
+
+udevadm settle
+
+need_shutdown
diff --git a/modules.d/90lvm/module-setup.sh b/modules.d/90lvm/module-setup.sh
new file mode 100755
index 0000000..7ba4c69
--- /dev/null
+++ b/modules.d/90lvm/module-setup.sh
@@ -0,0 +1,117 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ # No point trying to support lvm if the binaries are missing
+ require_binaries lvm grep || return 1
+
+ [[ $hostonly ]] || [[ $mount_needs ]] && {
+ for fs in "${host_fs_types[@]}"; do
+ [[ $fs == LVM*_member ]] && return 0
+ done
+ return 255
+ }
+
+ return 0
+}
+
+# called by dracut
+depends() {
+ # We depend on dm_mod being loaded
+ echo rootfs-block dm
+ return 0
+}
+
+# called by dracut
+cmdline() {
+ local _activated
+ declare -A _activated
+
+ for dev in "${!host_fs_types[@]}"; do
+ [[ -e /sys/block/${dev#/dev/}/dm/name ]] || continue
+ [[ -e /sys/block/${dev#/dev/}/dm/uuid ]] || continue
+ uuid=$(< "/sys/block/${dev#/dev/}/dm/uuid")
+ [[ ${uuid#LVM-} == "$uuid" ]] && continue
+ dev=$(< "/sys/block/${dev#/dev/}/dm/name")
+ eval "$(dmsetup splitname --nameprefixes --noheadings --rows "$dev" 2> /dev/null)"
+ [[ ${DM_VG_NAME} ]] && [[ ${DM_LV_NAME} ]] || return 1
+ if ! [[ ${_activated[DM_VG_NAME / DM_LV_NAME]} ]]; then
+ printf " rd.lvm.lv=%s " "${DM_VG_NAME}/${DM_LV_NAME} "
+ _activated["${DM_VG_NAME}/${DM_LV_NAME}"]=1
+ fi
+ done
+}
+
+installkernel() {
+ hostonly='' dracut_instmods -o -P ".*/(bcache/|md-cluster).*" "=drivers/md"
+}
+
+# called by dracut
+install() {
+ inst_multiple lvm grep
+
+ if [[ $hostonly_cmdline == "yes" ]]; then
+ local _lvmconf
+ _lvmconf=$(cmdline)
+ [[ $_lvmconf ]] && printf "%s\n" "$_lvmconf" >> "${initdir}/etc/cmdline.d/90lvm.conf"
+ fi
+
+ inst_rules "$moddir/64-lvm.rules"
+
+ if [[ $hostonly ]] || [[ $lvmconf == "yes" ]]; then
+ if [[ -f $dracutsysrootdir/etc/lvm/lvm.conf ]]; then
+ inst_simple -H /etc/lvm/lvm.conf
+ fi
+
+ export LVM_SUPPRESS_FD_WARNINGS=1
+ # Also install any files needed for LVM system id support.
+ if [[ -f $dracutsysrootdir/etc/lvm/lvmlocal.conf ]]; then
+ inst_simple -H /etc/lvm/lvmlocal.conf
+ fi
+ eval "$(lvm dumpconfig global/system_id_source &> /dev/null)"
+ if [ "$system_id_source" == "file" ]; then
+ eval "$(lvm dumpconfig global/system_id_file)"
+ if [ -f "$system_id_file" ]; then
+ inst_simple -H "$system_id_file"
+ fi
+ fi
+ unset LVM_SUPPRESS_FD_WARNINGS
+ fi
+
+ inst_rules 11-dm-lvm.rules
+
+ # Gentoo ebuild for LVM2 prior to 2.02.63-r1 doesn't install above rules
+ # files, but provides the one below:
+ inst_rules 64-device-mapper.rules
+ # debian udev rules
+ inst_rules 56-lvm.rules 60-persistent-storage-lvm.rules
+
+ inst_script "$moddir/lvm_scan.sh" /sbin/lvm_scan
+ inst_hook cmdline 30 "$moddir/parse-lvm.sh"
+
+ if [[ $hostonly ]] && find_binary lvs &> /dev/null; then
+ for dev in "${!host_fs_types[@]}"; do
+ [[ -e /sys/block/${dev#/dev/}/dm/name ]] || continue
+ dev=$(< "/sys/block/${dev#/dev/}/dm/name")
+ eval "$(dmsetup splitname --nameprefixes --noheadings --rows "$dev" 2> /dev/null)"
+ # shellcheck disable=SC2015
+ [[ ${DM_VG_NAME} ]] && [[ ${DM_LV_NAME} ]] || continue
+ case "$(lvs --noheadings -o segtype "${DM_VG_NAME}" 2> /dev/null)" in
+ *thin* | *cache* | *era*)
+ inst_multiple -o thin_dump thin_restore thin_check thin_repair \
+ cache_dump cache_restore cache_check cache_repair \
+ era_check era_dump era_invalidate era_restore
+ break
+ ;;
+ esac
+ done
+ fi
+
+ if ! [[ $hostonly ]]; then
+ inst_multiple -o thin_dump thin_restore thin_check thin_repair \
+ cache_dump cache_restore cache_check cache_repair \
+ era_check era_dump era_invalidate era_restore
+ fi
+
+ dracut_need_initqueue
+}
diff --git a/modules.d/90lvm/parse-lvm.sh b/modules.d/90lvm/parse-lvm.sh
new file mode 100755
index 0000000..d774882
--- /dev/null
+++ b/modules.d/90lvm/parse-lvm.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+if [ -e /etc/lvm/lvm.conf ] && ! getargbool 1 rd.lvm.conf -d -n rd_NO_LVMCONF; then
+ rm -f -- /etc/lvm/lvm.conf
+fi
+
+LV_DEVS="$(getargs rd.lvm.vg -d rd_LVM_VG=) $(getargs rd.lvm.lv -d rd_LVM_LV=)"
+
+if ! getargbool 1 rd.lvm -d -n rd_NO_LVM \
+ || { [ -z "$LV_DEVS" ] && ! getargbool 0 rd.auto; }; then
+ info "rd.lvm=0: removing LVM activation"
+ rm -f -- /etc/udev/rules.d/64-lvm*.rules
+else
+ for dev in $LV_DEVS; do
+ wait_for_dev -n "/dev/$dev"
+ done
+fi
diff --git a/modules.d/90mdraid/59-persistent-storage-md.rules b/modules.d/90mdraid/59-persistent-storage-md.rules
new file mode 100644
index 0000000..0d745cc
--- /dev/null
+++ b/modules.d/90mdraid/59-persistent-storage-md.rules
@@ -0,0 +1,24 @@
+SUBSYSTEM!="block", GOTO="md_end"
+ACTION!="add|change", GOTO="md_end"
+# Also don't process disks that are slated to be a multipath device
+ENV{DM_MULTIPATH_DEVICE_PATH}=="1", GOTO="md_end"
+
+KERNEL!="md[0-9]*|md_d[0-9]*|md/*", KERNEL!="md*", GOTO="md_end"
+
+# partitions have no md/{array_state,metadata_version}
+ENV{DEVTYPE}=="partition", GOTO="md_ignore_state"
+
+# container devices have a metadata version of e.g. 'external:ddf' and
+# never leave state 'inactive'
+ATTR{md/metadata_version}=="external:[A-Za-z]*", ATTR{md/array_state}=="inactive", GOTO="md_ignore_state"
+TEST!="md/array_state", GOTO="md_end"
+ATTR{md/array_state}=="|clear|inactive", GOTO="md_end"
+
+LABEL="md_ignore_state"
+
+IMPORT{program}="/sbin/mdadm --detail --export $tempnode"
+IMPORT{builtin}="blkid"
+OPTIONS+="link_priority=100"
+OPTIONS+="watch"
+OPTIONS+="db_persist"
+LABEL="md_end"
diff --git a/modules.d/90mdraid/65-md-incremental-imsm.rules b/modules.d/90mdraid/65-md-incremental-imsm.rules
new file mode 100644
index 0000000..6697f15
--- /dev/null
+++ b/modules.d/90mdraid/65-md-incremental-imsm.rules
@@ -0,0 +1,44 @@
+# This file causes block devices with Linux RAID (mdadm) signatures to
+# automatically cause mdadm to be run.
+# See udev(8) for syntax
+
+ACTION!="add|change", GOTO="md_end"
+SUBSYSTEM!="block", GOTO="md_end"
+ENV{rd_NO_MD}=="?*", GOTO="md_end"
+KERNEL=="md*", ENV{ID_FS_TYPE}!="linux_raid_member", GOTO="md_end"
+KERNEL=="md*", ACTION!="change", GOTO="md_end"
+
+# Also don't process disks that are slated to be a multipath device
+ENV{DM_MULTIPATH_DEVICE_PATH}=="1", GOTO="md_end"
+
+ENV{ID_FS_TYPE}=="ddf_raid_member|isw_raid_member|linux_raid_member", GOTO="md_try"
+GOTO="md_end"
+
+LABEL="md_try"
+ENV{ID_FS_TYPE}=="isw_raid_member", ENV{rd_NO_MDIMSM}=="?*", GOTO="md_end"
+ENV{ID_FS_TYPE}=="ddf_raid_member", ENV{rd_NO_MDDDF}=="?*", GOTO="md_end"
+
+# already done ?
+PROGRAM="/bin/sh -c 'for i in $sys/$devpath/holders/md[0-9_]*; do [ -e $$i ] && exit 0; done; exit 1;' ", \
+ GOTO="md_end"
+
+# for native arrays - array's uuid has to be specified
+# for containers - container's uuid has to be specified
+# TODO : how to get embedded array's uuid having container's component ?
+#
+# UUID CHECK
+
+ENV{DEVTYPE}!="partition", \
+ RUN+="/sbin/partx -d --nr 1-1024 $env{DEVNAME}"
+
+RUN+="/sbin/initqueue --timeout --name 50-mdraid_start --onetime --unique /sbin/mdraid_start"
+
+#
+# Incrementally build the md array; this will automatically assemble
+# any eventual containers as well (imsm, ddf)
+#
+LABEL="md_incremental"
+
+RUN+="/sbin/mdadm -I $env{DEVNAME}"
+
+LABEL="md_end"
diff --git a/modules.d/90mdraid/md-shutdown.sh b/modules.d/90mdraid/md-shutdown.sh
new file mode 100755
index 0000000..ca768a9
--- /dev/null
+++ b/modules.d/90mdraid/md-shutdown.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+_do_md_shutdown() {
+ local ret
+ local final="$1"
+ info "Waiting for mdraid devices to be clean."
+ mdadm -vv --wait-clean --scan | vinfo
+ ret=$?
+ info "Disassembling mdraid devices."
+ mdadm -vv --stop --scan | vinfo
+ ret=$((ret + $?))
+ if [ "x$final" != "x" ]; then
+ info "/proc/mdstat:"
+ vinfo < /proc/mdstat
+ fi
+ return $ret
+}
+
+if command -v mdadm > /dev/null; then
+ _do_md_shutdown "$1"
+else
+ :
+fi
diff --git a/modules.d/90mdraid/mdmon-pre-shutdown.sh b/modules.d/90mdraid/mdmon-pre-shutdown.sh
new file mode 100755
index 0000000..a5cd850
--- /dev/null
+++ b/modules.d/90mdraid/mdmon-pre-shutdown.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+_do_mdmon_takeover() {
+ local ret
+ mdmon --takeover --all
+ ret=$?
+ [ $ret -eq 0 ] && info "Taking over mdmon processes."
+ return $ret
+}
+
+if command -v mdmon > /dev/null; then
+ _do_mdmon_takeover "$1"
+fi
diff --git a/modules.d/90mdraid/mdmon-pre-udev.sh b/modules.d/90mdraid/mdmon-pre-udev.sh
new file mode 100755
index 0000000..b15cca8
--- /dev/null
+++ b/modules.d/90mdraid/mdmon-pre-udev.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+# save state dir for mdmon/mdadm for the real root
+[ -d /run/mdadm ] || mkdir -m 0755 -p /run/mdadm
+# backward compat link
diff --git a/modules.d/90mdraid/mdraid-cleanup.sh b/modules.d/90mdraid/mdraid-cleanup.sh
new file mode 100755
index 0000000..ce50733
--- /dev/null
+++ b/modules.d/90mdraid/mdraid-cleanup.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+containers=""
+for md in /dev/md[0-9_]*; do
+ [ -b "$md" ] || continue
+ udevinfo="$(udevadm info --query=property --name="$md")"
+ strstr "$udevinfo" "DEVTYPE=partition" && continue
+ if strstr "$udevinfo" "MD_LEVEL=container"; then
+ containers="$containers $md"
+ continue
+ fi
+ mdadm -S "$md" > /dev/null 2>&1
+done
+
+for md in $containers; do
+ mdadm -S "$md" > /dev/null 2>&1
+done
+
+unset containers udevinfo
diff --git a/modules.d/90mdraid/mdraid-needshutdown.sh b/modules.d/90mdraid/mdraid-needshutdown.sh
new file mode 100755
index 0000000..f248c4b
--- /dev/null
+++ b/modules.d/90mdraid/mdraid-needshutdown.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+for md in /dev/md[0-9_]*; do
+ [ -b "$md" ] || continue
+ need_shutdown
+ break
+done
diff --git a/modules.d/90mdraid/mdraid-waitclean.sh b/modules.d/90mdraid/mdraid-waitclean.sh
new file mode 100755
index 0000000..9317962
--- /dev/null
+++ b/modules.d/90mdraid/mdraid-waitclean.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+if getargbool 0 rd.md.waitclean; then
+ type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+ containers=""
+ for md in /dev/md[0-9_]*; do
+ [ -b "$md" ] || continue
+ udevinfo="$(udevadm info --query=property --name="$md")"
+ strstr "$udevinfo" "DEVTYPE=partition" && continue
+ if strstr "$udevinfo" "MD_LEVEL=container"; then
+ containers="$containers $md"
+ continue
+ fi
+ info "Waiting for $md to become clean"
+ mdadm -W "$md" > /dev/null 2>&1
+ done
+
+ for md in $containers; do
+ info "Waiting for $md to become clean"
+ mdadm -W "$md" > /dev/null 2>&1
+ done
+
+ unset containers udevinfo
+fi
diff --git a/modules.d/90mdraid/mdraid_start.sh b/modules.d/90mdraid/mdraid_start.sh
new file mode 100755
index 0000000..d8c5de2
--- /dev/null
+++ b/modules.d/90mdraid/mdraid_start.sh
@@ -0,0 +1,70 @@
+#!/bin/sh
+
+type getargs > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+_md_start() {
+ local _udevinfo
+ local _path_s
+ local _path_d
+ local _md="$1"
+
+ _udevinfo="$(udevadm info --query=property --name="${_md}")"
+ strstr "$_udevinfo" "MD_LEVEL=container" && return 0
+ strstr "$_udevinfo" "DEVTYPE=partition" && return 0
+
+ _path_s="/sys/$(udevadm info -q path -n "${_md}")/md/array_state"
+ [ ! -r "$_path_s" ] && return 0
+
+ # inactive ?
+ [ "$(cat "$_path_s")" != "inactive" ] && return 0
+
+ mdadm -R "${_md}" 2>&1 | vinfo
+
+ # still inactive ?
+ [ "$(cat "$_path_s")" = "inactive" ] && return 0
+
+ _path_d="${_path_s%/*}/degraded"
+ [ ! -r "$_path_d" ] && return 0
+ : > "$hookdir"/initqueue/work
+}
+
+_md_force_run() {
+ local _md
+ local _UUID
+ local _MD_UUID
+
+ _MD_UUID=$(getargs rd.md.uuid -d rd_MD_UUID=)
+ [ -n "$_MD_UUID" ] || getargbool 0 rd.auto || return
+
+ if [ -n "$_MD_UUID" ]; then
+ _MD_UUID=$(str_replace "$_MD_UUID" "-" "")
+ _MD_UUID=$(str_replace "$_MD_UUID" ":" "")
+
+ for _md in /dev/md[0-9_]*; do
+ [ -b "$_md" ] || continue
+ _UUID=$(
+ /sbin/mdadm -D --export "$_md" \
+ | while read -r line || [ -n "$line" ]; do
+ str_starts "$line" "MD_UUID=" || continue
+ printf "%s" "${line#MD_UUID=}"
+ done
+ )
+
+ [ -z "$_UUID" ] && continue
+ _UUID=$(str_replace "$_UUID" ":" "")
+
+ # check if we should handle this device
+ strstr "$_MD_UUID" "$_UUID" || continue
+
+ _md_start "${_md}"
+ done
+ else
+ # try to force-run anything not running yet
+ for _md in /dev/md[0-9_]*; do
+ [ -b "$_md" ] || continue
+ _md_start "${_md}"
+ done
+ fi
+}
+
+_md_force_run
diff --git a/modules.d/90mdraid/module-setup.sh b/modules.d/90mdraid/module-setup.sh
new file mode 100755
index 0000000..6179a98
--- /dev/null
+++ b/modules.d/90mdraid/module-setup.sh
@@ -0,0 +1,139 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ local dev holder
+
+ # No mdadm? No mdraid support.
+ require_binaries mdadm expr || return 1
+
+ [[ $hostonly ]] || [[ $mount_needs ]] && {
+ for dev in "${!host_fs_types[@]}"; do
+ [[ ${host_fs_types[$dev]} != *_raid_member ]] && continue
+
+ DEVPATH=$(get_devpath_block "$dev")
+
+ for holder in "$DEVPATH"/holders/*; do
+ [[ -e $holder ]] || continue
+ [[ -e "$holder/md" ]] && return 0
+ break
+ done
+
+ done
+ return 255
+ }
+
+ return 0
+}
+
+# called by dracut
+depends() {
+ echo rootfs-block
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ instmods '=drivers/md'
+}
+
+# called by dracut
+cmdline() {
+ local _activated dev line UUID
+ declare -A _activated
+
+ for dev in "${!host_fs_types[@]}"; do
+ [[ ${host_fs_types[$dev]} != *_raid_member ]] && continue
+
+ UUID=$(
+ /sbin/mdadm --examine --export "$dev" \
+ | while read -r line || [[ "$line" ]]; do
+ [[ ${line#MD_UUID=} == "$line" ]] && continue
+ printf "%s" "${line#MD_UUID=} "
+ done
+ )
+
+ [[ -z $UUID ]] && continue
+
+ if ! [[ ${_activated[${UUID}]} ]]; then
+ printf "%s" " rd.md.uuid=${UUID}"
+ _activated["${UUID}"]=1
+ fi
+
+ done
+}
+
+# called by dracut
+install() {
+ local rule rule_path
+ inst_multiple cat expr
+ inst_multiple -o mdmon
+ inst "$(command -v partx)" /sbin/partx
+ inst "$(command -v mdadm)" /sbin/mdadm
+
+ if [[ $hostonly_cmdline == "yes" ]]; then
+ local _raidconf
+ _raidconf=$(cmdline)
+ [[ $_raidconf ]] && printf "%s\n" "$_raidconf" >> "${initdir}/etc/cmdline.d/90mdraid.conf"
+ fi
+
+ # <mdadm-3.3 udev rule
+ inst_rules 64-md-raid.rules
+ # >=mdadm-3.3 udev rules
+ inst_rules 63-md-raid-arrays.rules 64-md-raid-assembly.rules
+ # remove incremental assembly from stock rules, so they don't shadow
+ # 65-md-inc*.rules and its fine-grained controls, or cause other problems
+ # when we explicitly don't want certain components to be incrementally
+ # assembled
+ for rule in 64-md-raid.rules 64-md-raid-assembly.rules; do
+ rule_path="${initdir}${udevdir}/rules.d/${rule}"
+ # shellcheck disable=SC2016
+ [ -f "${rule_path}" ] && sed -i -r \
+ -e '/(RUN|IMPORT\{program\})\+?="[[:alpha:]/]*mdadm[[:blank:]]+(--incremental|-I)[[:blank:]]+(--export )?(\$env\{DEVNAME\}|\$tempnode|\$devnode)/d' \
+ "${rule_path}"
+ done
+
+ inst_rules "$moddir/65-md-incremental-imsm.rules"
+
+ inst_rules "$moddir/59-persistent-storage-md.rules"
+
+ if [[ $hostonly ]] || [[ $mdadmconf == "yes" ]]; then
+ if [[ -f $dracutsysrootdir/etc/mdadm.conf ]]; then
+ inst -H /etc/mdadm.conf
+ else
+ [[ -f $dracutsysrootdir/etc/mdadm/mdadm.conf ]] && inst -H /etc/mdadm/mdadm.conf /etc/mdadm.conf
+ fi
+ if [[ -d $dracutsysrootdir/etc/mdadm.conf.d ]]; then
+ local f
+ inst_dir /etc/mdadm.conf.d
+ for f in /etc/mdadm.conf.d/*.conf; do
+ [[ -f "$dracutsysrootdir$f" ]] || continue
+ inst -H "$f"
+ done
+ fi
+ fi
+
+ inst_hook pre-udev 30 "$moddir/mdmon-pre-udev.sh"
+ inst_hook pre-trigger 30 "$moddir/parse-md.sh"
+ inst_hook pre-mount 10 "$moddir/mdraid-waitclean.sh"
+ inst_hook cleanup 99 "$moddir/mdraid-needshutdown.sh"
+ inst_hook shutdown 30 "$moddir/md-shutdown.sh"
+ inst_script "$moddir/mdraid-cleanup.sh" /sbin/mdraid-cleanup
+ inst_script "$moddir/mdraid_start.sh" /sbin/mdraid_start
+ if dracut_module_included "systemd"; then
+ if [[ -e $dracutsysrootdir$systemdsystemunitdir/mdmon@.service ]]; then
+ inst_simple "$systemdsystemunitdir"/mdmon@.service
+ fi
+ if [[ -e $dracutsysrootdir$systemdsystemunitdir/mdadm-last-resort@.service ]]; then
+ inst_simple "$systemdsystemunitdir"/mdadm-last-resort@.service
+ fi
+ if [[ -e $dracutsysrootdir$systemdsystemunitdir/mdadm-last-resort@.timer ]]; then
+ inst_simple "$systemdsystemunitdir"/mdadm-last-resort@.timer
+ fi
+ if [[ -e $dracutsysrootdir$systemdsystemunitdir/mdadm-grow-continue@.service ]]; then
+ inst_simple "$systemdsystemunitdir"/mdadm-grow-continue@.service
+ fi
+ fi
+ inst_hook pre-shutdown 30 "$moddir/mdmon-pre-shutdown.sh"
+ dracut_need_initqueue
+}
diff --git a/modules.d/90mdraid/parse-md.sh b/modules.d/90mdraid/parse-md.sh
new file mode 100755
index 0000000..4d3a6b2
--- /dev/null
+++ b/modules.d/90mdraid/parse-md.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+# we really need to use `expr substr` with dash
+# shellcheck disable=SC2003 disable=SC2308
+
+MD_UUID=$(getargs rd.md.uuid -d rd_MD_UUID=)
+# normalize the uuid
+MD_UUID=$(str_replace "$MD_UUID" "-" "")
+MD_UUID=$(str_replace "$MD_UUID" ":" "")
+
+if { [ -z "$MD_UUID" ] && ! getargbool 0 rd.auto; } || ! getargbool 1 rd.md -d -n rd_NO_MD; then
+ info "rd.md=0: removing MD RAID activation"
+ udevproperty rd_NO_MD=1
+else
+ # rewrite the md rules to only process the specified raid array
+ if [ -n "$MD_UUID" ]; then
+ for f in /etc/udev/rules.d/65-md-incremental*.rules; do
+ [ -e "$f" ] || continue
+ while read -r line || [ -n "$line" ]; do
+ if [ "${line%%UUID CHECK}" != "$line" ]; then
+ for uuid in $MD_UUID; do
+ printf 'ENV{ID_FS_UUID}=="%s", GOTO="md_uuid_ok"\n' "$(expr substr "$uuid" 1 8)-$(expr substr "$uuid" 9 4)-$(expr substr "$uuid" 13 4)-$(expr substr "$uuid" 17 4)-$(expr substr "$uuid" 21 12)"
+ done
+ # shellcheck disable=SC2016
+ printf 'IMPORT{program}="/sbin/mdadm --examine --export $tempnode"\n'
+ for uuid in $MD_UUID; do
+ printf 'ENV{MD_UUID}=="%s", GOTO="md_uuid_ok"\n' "$(expr substr "$uuid" 1 8):$(expr substr "$uuid" 9 8):$(expr substr "$uuid" 17 8):$(expr substr "$uuid" 25 8)"
+ done
+ printf 'GOTO="md_end"\n'
+ printf 'LABEL="md_uuid_ok"\n'
+ else
+ echo "$line"
+ fi
+ done < "${f}" > "${f}.new"
+ mv "${f}.new" "$f"
+ done
+ for uuid in $MD_UUID; do
+ uuid="$(expr substr "$uuid" 1 8):$(expr substr "$uuid" 9 8):$(expr substr "$uuid" 17 8):$(expr substr "$uuid" 25 8)"
+ wait_for_dev "/dev/disk/by-id/md-uuid-${uuid}"
+ done
+ fi
+fi
+
+if [ -e /etc/mdadm.conf ] && getargbool 1 rd.md.conf -d -n rd_NO_MDADMCONF; then
+ udevproperty rd_MDADMCONF=1
+ rm -f -- "$hookdir"/pre-pivot/*mdraid-cleanup.sh
+fi
+
+if ! getargbool 1 rd.md.conf -d -n rd_NO_MDADMCONF; then
+ rm -f -- /etc/mdadm/mdadm.conf /etc/mdadm.conf
+ ln -s "$(command -v mdraid-cleanup)" "$hookdir"/pre-pivot/31-mdraid-cleanup.sh 2> /dev/null
+fi
+
+# noiswmd nodmraid for anaconda / rc.sysinit compatibility
+# note nodmraid really means nobiosraid, so we don't want MDIMSM then either
+if ! getargbool 1 rd.md.imsm -d -n rd_NO_MDIMSM -n noiswmd -n nodmraid; then
+ info "no MD RAID for imsm/isw raids"
+ udevproperty rd_NO_MDIMSM=1
+fi
+
+# same thing with ddf containers
+if ! getargbool 1 rd.md.ddf -n rd_NO_MDDDF -n noddfmd -n nodmraid; then
+ info "no MD RAID for SNIA ddf raids"
+ udevproperty rd_NO_MDDDF=1
+fi
diff --git a/modules.d/90multipath/module-setup.sh b/modules.d/90multipath/module-setup.sh
new file mode 100755
index 0000000..9c3e629
--- /dev/null
+++ b/modules.d/90multipath/module-setup.sh
@@ -0,0 +1,154 @@
+#!/bin/bash
+
+is_mpath() {
+ local _dev=$1
+ [ -e /sys/dev/block/"$_dev"/dm/uuid ] || return 1
+ [[ $(cat /sys/dev/block/"$_dev"/dm/uuid) =~ mpath- ]] && return 0
+ return 1
+}
+
+majmin_to_mpath_dev() {
+ local _dev
+ for i in /dev/mapper/*; do
+ [[ $i == /dev/mapper/control ]] && continue
+ _dev=$(get_maj_min "$i")
+ if [ "$_dev" = "$1" ]; then
+ echo "$i"
+ return
+ fi
+ done
+}
+
+# called by dracut
+check() {
+ [[ $hostonly ]] || [[ $mount_needs ]] && {
+ for_each_host_dev_and_slaves is_mpath || return 255
+ }
+
+ # if there's no multipath binary, no go.
+ require_binaries multipath || return 1
+ require_binaries kpartx || return 1
+
+ return 0
+}
+
+# called by dracut
+depends() {
+ echo rootfs-block
+ echo dm
+ return 0
+}
+
+# called by dracut
+cmdline() {
+ for m in scsi_dh_alua scsi_dh_emc scsi_dh_rdac dm_multipath; do
+ if grep -m 1 -q "$m" /proc/modules; then
+ printf 'rd.driver.pre=%s ' "$m"
+ fi
+ done
+}
+
+# called by dracut
+installkernel() {
+ local _arch=${DRACUT_ARCH:-$(uname -m)}
+ local _funcs='scsi_register_device_handler|dm_dirty_log_type_register|dm_register_path_selector|dm_register_target'
+
+ if [ "$_arch" = "s390" -o "$_arch" = "s390x" ]; then
+ _s390drivers="=drivers/s390/scsi"
+ fi
+
+ hostonly='' dracut_instmods -o -s "$_funcs" "=drivers/scsi" "=drivers/md" ${_s390drivers:+"$_s390drivers"}
+}
+
+mpathconf_installed() {
+ command -v mpathconf &> /dev/null
+}
+
+# called by dracut
+install() {
+ local -A _allow
+ local config_dir
+
+ add_hostonly_mpath_conf() {
+ if is_mpath "$1"; then
+ local _dev
+
+ _dev=$(majmin_to_mpath_dev "$1")
+ [ -z "$_dev" ] && return
+ _allow["$_dev"]="$_dev"
+ fi
+ }
+
+ local k v
+ while read -r k v; do
+ if [[ $k == "config_dir" ]]; then
+ v="${v#\"}"
+ config_dir="${v%\"}"
+ break
+ fi
+ done < <(multipath -t 2> /dev/null)
+ [[ -d $config_dir ]] || config_dir=/etc/multipath/conf.d
+
+ inst_multiple \
+ pkill \
+ kpartx \
+ dmsetup \
+ multipath \
+ multipathd
+
+ inst_multiple -o \
+ mpath_wait \
+ mpathconf \
+ mpathpersist \
+ xdrgetprio \
+ xdrgetuid \
+ /etc/xdrdevices.conf \
+ /etc/multipath.conf \
+ /etc/multipath/* \
+ "$config_dir"/* \
+ "$tmpfilesdir/multipath.conf"
+
+ mpathconf_installed \
+ && [[ $hostonly ]] && [[ $hostonly_mode == "strict" ]] && {
+ for_each_host_dev_and_slaves_all add_hostonly_mpath_conf
+ if ((${#_allow[@]} > 0)); then
+ local -a _args
+ local _dev
+ for _dev in "${_allow[@]}"; do
+ _args+=("--allow" "$_dev")
+ done
+ mpathconf "${_args[@]}" --outfile "${initdir}"/etc/multipath.conf
+ fi
+ }
+
+ inst "$(command -v partx)" /sbin/partx
+
+ inst_libdir_file "libmultipath*" "multipath/*"
+ inst_libdir_file 'libgcc_s.so*'
+
+ if [[ $hostonly_cmdline ]]; then
+ local _conf
+ _conf=$(cmdline)
+ [[ $_conf ]] && echo "$_conf" >> "${initdir}/etc/cmdline.d/90multipath.conf"
+ fi
+
+ if dracut_module_included "systemd"; then
+ if mpathconf_installed; then
+ inst_simple "${moddir}/multipathd-configure.service" "${systemdsystemunitdir}/multipathd-configure.service"
+ $SYSTEMCTL -q --root "$initdir" enable multipathd-configure.service
+ fi
+ inst_simple "${moddir}/multipathd.service" "${systemdsystemunitdir}/multipathd.service"
+ $SYSTEMCTL -q --root "$initdir" enable multipathd.service
+ else
+ inst_hook pre-trigger 02 "$moddir/multipathd.sh"
+ inst_hook cleanup 02 "$moddir/multipathd-stop.sh"
+ fi
+
+ inst_hook cleanup 80 "$moddir/multipathd-needshutdown.sh"
+ inst_hook shutdown 20 "$moddir/multipath-shutdown.sh"
+
+ inst_rules 40-multipath.rules 56-multipath.rules \
+ 62-multipath.rules 65-multipath.rules \
+ 66-kpartx.rules 67-kpartx-compat.rules \
+ 11-dm-mpath.rules 11-dm-parts.rules
+}
diff --git a/modules.d/90multipath/multipath-shutdown.sh b/modules.d/90multipath/multipath-shutdown.sh
new file mode 100755
index 0000000..220da8f
--- /dev/null
+++ b/modules.d/90multipath/multipath-shutdown.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for i in $(multipath -l -v1); do
+ if ! dmsetup table "$i" | sed -n '/.*queue_if_no_path.*/q1'; then
+ dmsetup message "$i" 0 fail_if_no_path
+ fi
+done
diff --git a/modules.d/90multipath/multipathd-configure.service b/modules.d/90multipath/multipathd-configure.service
new file mode 100644
index 0000000..a2baec7
--- /dev/null
+++ b/modules.d/90multipath/multipathd-configure.service
@@ -0,0 +1,21 @@
+[Unit]
+Description=Device-Mapper Multipath Default Configuration
+Before=iscsi.service iscsid.service lvm2-activation-early.service
+Wants=systemd-udev-trigger.service systemd-udev-settle.service local-fs-pre.target
+After=systemd-udev-trigger.service systemd-udev-settle.service
+Before=local-fs-pre.target multipathd.service
+DefaultDependencies=no
+Conflicts=shutdown.target
+
+ConditionKernelCommandLine=rd.multipath=default
+ConditionPathExists=!/etc/multipath.conf
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+# mpathconf requires /etc/multipath to already exist
+ExecStartPre=-/usr/bin/mkdir -p /etc/multipath
+ExecStart=/usr/sbin/mpathconf --enable
+
+[Install]
+WantedBy=sysinit.target
diff --git a/modules.d/90multipath/multipathd-needshutdown.sh b/modules.d/90multipath/multipathd-needshutdown.sh
new file mode 100755
index 0000000..6dc68bb
--- /dev/null
+++ b/modules.d/90multipath/multipathd-needshutdown.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+type need_shutdown > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+for i in $(multipath -l -v1); do
+ if dmsetup table "$i" | sed -n '/.*queue_if_no_path.*/q1'; then
+ need_shutdown
+ break
+ fi
+done
diff --git a/modules.d/90multipath/multipathd-stop.sh b/modules.d/90multipath/multipathd-stop.sh
new file mode 100755
index 0000000..05181b4
--- /dev/null
+++ b/modules.d/90multipath/multipathd-stop.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+type pidof > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+if [ -e /etc/multipath.conf ]; then
+ pkill multipathd > /dev/null 2>&1
+
+ if pidof multipathd > /dev/null 2>&1; then
+ sleep 0.2
+ fi
+
+ if pidof multipathd > /dev/null 2>&1; then
+ pkill -9 multipathd > /dev/null 2>&1
+ fi
+fi
diff --git a/modules.d/90multipath/multipathd.service b/modules.d/90multipath/multipathd.service
new file mode 100644
index 0000000..1680cdf
--- /dev/null
+++ b/modules.d/90multipath/multipathd.service
@@ -0,0 +1,27 @@
+[Unit]
+Description=Device-Mapper Multipath Device Controller
+Before=lvm2-activation-early.service
+Before=local-fs-pre.target blk-availability.service shutdown.target
+Wants=systemd-udevd-kernel.socket
+After=systemd-udevd-kernel.socket
+After=multipathd.socket systemd-remount-fs.service
+Before=initrd-cleanup.service
+DefaultDependencies=no
+Conflicts=shutdown.target
+Conflicts=initrd-cleanup.service
+ConditionKernelCommandLine=!nompath
+ConditionKernelCommandLine=!rd.multipath=0
+ConditionKernelCommandLine=!rd_NO_MULTIPATH
+ConditionKernelCommandLine=!multipath=off
+ConditionVirtualization=!container
+
+[Service]
+Type=notify
+NotifyAccess=main
+ExecStartPre=-/sbin/modprobe dm-multipath
+ExecStart=/sbin/multipathd -d -s
+ExecReload=/sbin/multipathd reconfigure
+TasksMax=infinity
+
+[Install]
+WantedBy=sysinit.target
diff --git a/modules.d/90multipath/multipathd.sh b/modules.d/90multipath/multipathd.sh
new file mode 100755
index 0000000..1e26c1d
--- /dev/null
+++ b/modules.d/90multipath/multipathd.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+if [ "$(getarg rd.multipath)" = "default" ] && [ ! -e /etc/multipath.conf ]; then
+ # mpathconf requires /etc/multipath to already exist
+ mkdir -p /etc/multipath
+ mpathconf --enable
+fi
+
+if getargbool 1 rd.multipath -d -n rd_NO_MULTIPATH && [ -e /etc/multipath.conf ]; then
+ modprobe dm-multipath
+ multipathd -B || multipathd
+ need_shutdown
+else
+ rm -- /etc/udev/rules.d/??-multipath.rules 2> /dev/null
+fi
diff --git a/modules.d/90nvdimm/module-setup.sh b/modules.d/90nvdimm/module-setup.sh
new file mode 100755
index 0000000..8d33610
--- /dev/null
+++ b/modules.d/90nvdimm/module-setup.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ if [[ ! $hostonly ]]; then
+ return 0
+ fi
+ [[ $DRACUT_KERNEL_MODALIASES && -f $DRACUT_KERNEL_MODALIASES ]] \
+ && grep -q libnvdimm "$DRACUT_KERNEL_MODALIASES" && return 0
+ return 255
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ # Directories to search for NVDIMM "providers" (firmware drivers)
+ # These modules call "nvdimm_bus_register()".
+ #instmods() will take care of hostonly
+ dracut_instmods -o -s nvdimm_bus_register \
+ '=drivers/nvdimm' \
+ '=drivers/acpi' \
+ '=arch/powerpc'
+}
+
+# called by dracut
+install() {
+ inst_multiple -o ndctl /etc/ndctl/keys/tpm.handle "/etc/ndctl/keys/*.blob"
+}
diff --git a/modules.d/90overlayfs/module-setup.sh b/modules.d/90overlayfs/module-setup.sh
new file mode 100755
index 0000000..893e2dc
--- /dev/null
+++ b/modules.d/90overlayfs/module-setup.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+check() {
+ [[ $hostonly ]] && return 1
+ return 255
+}
+
+depends() {
+ echo base
+}
+
+installkernel() {
+ instmods overlay
+}
+
+install() {
+ inst_hook mount 01 "$moddir/mount-overlayfs.sh"
+ inst_hook pre-mount 01 "$moddir/prepare-overlayfs.sh"
+}
diff --git a/modules.d/90overlayfs/mount-overlayfs.sh b/modules.d/90overlayfs/mount-overlayfs.sh
new file mode 100755
index 0000000..e1d23fb
--- /dev/null
+++ b/modules.d/90overlayfs/mount-overlayfs.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+getargbool 0 rd.live.overlay.overlayfs && overlayfs="yes"
+getargbool 0 rd.live.overlay.readonly -d -y readonly_overlay && readonly_overlay="--readonly" || readonly_overlay=""
+
+ROOTFLAGS="$(getarg rootflags)"
+
+if [ -n "$overlayfs" ]; then
+ if [ -n "$readonly_overlay" ] && [ -h /run/overlayfs-r ]; then
+ ovlfs=lowerdir=/run/overlayfs-r:/run/rootfsbase
+ else
+ ovlfs=lowerdir=/run/rootfsbase
+ fi
+
+ if ! strstr "$(cat /proc/mounts)" LiveOS_rootfs; then
+ mount -t overlay LiveOS_rootfs -o "$ROOTFLAGS,$ovlfs",upperdir=/run/overlayfs,workdir=/run/ovlwork "$NEWROOT"
+ fi
+fi
diff --git a/modules.d/90overlayfs/prepare-overlayfs.sh b/modules.d/90overlayfs/prepare-overlayfs.sh
new file mode 100755
index 0000000..87bcc19
--- /dev/null
+++ b/modules.d/90overlayfs/prepare-overlayfs.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+getargbool 0 rd.live.overlay.overlayfs && overlayfs="yes"
+getargbool 0 rd.live.overlay.reset -d -y reset_overlay && reset_overlay="yes"
+
+if [ -n "$overlayfs" ]; then
+ if ! [ -e /run/rootfsbase ]; then
+ mkdir -m 0755 -p /run/rootfsbase
+ mount --bind "$NEWROOT" /run/rootfsbase
+ fi
+
+ mkdir -m 0755 -p /run/overlayfs
+ mkdir -m 0755 -p /run/ovlwork
+ if [ -n "$reset_overlay" ] && [ -h /run/overlayfs ]; then
+ ovlfsdir=$(readlink /run/overlayfs)
+ info "Resetting the OverlayFS overlay directory."
+ rm -r -- "${ovlfsdir:?}"/* "${ovlfsdir:?}"/.* > /dev/null 2>&1
+ fi
+fi
diff --git a/modules.d/90ppcmac/load-thermal.sh b/modules.d/90ppcmac/load-thermal.sh
new file mode 100755
index 0000000..72f2581
--- /dev/null
+++ b/modules.d/90ppcmac/load-thermal.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+#
+# This hook attempts to load the appropriate thermal modules
+# for PowerPC Macs depending on the specific machine you have.
+
+[ -r /proc/cpuinfo ] || exit 0
+
+load_windfarm() {
+ local pm_model
+ pm_model="$(sed -n '/model/p' /proc/cpuinfo)"
+ pm_model="${pm_model##*: }"
+
+ # load quietly and respect the blacklist
+ # this way if the modules are for some reason missing, it will
+ # still exit successfully and not affect the boot process
+ case "$pm_model" in
+ PowerMac3,6) modprobe -b -q therm_windtunnel ;;
+ PowerMac7,2 | PowerMac7,3) modprobe -b -q windfarm_pm72 ;;
+ PowerMac8,1 | PowerMac8,2) modprobe -b -q windfarm_pm81 ;;
+ PowerMac9,1) modprobe -b -q windfarm_pm91 ;;
+ PowerMac11,2) modprobe -b -q windfarm_pm112 ;;
+ PowerMac12,1) modprobe -b -q windfarm_pm121 ;;
+ RackMac3,1) modprobe -b -q windfarm_rm31 ;;
+ *) ;;
+ esac
+
+ return 0
+}
+
+load_windfarm
diff --git a/modules.d/90ppcmac/module-setup.sh b/modules.d/90ppcmac/module-setup.sh
new file mode 100755
index 0000000..83f54de
--- /dev/null
+++ b/modules.d/90ppcmac/module-setup.sh
@@ -0,0 +1,83 @@
+#!/bin/bash
+#
+# This module attempts to properly deal with thermal behavior on PowerPC
+# based Mac systems, by installing the model-appropriate (when hostonly)
+# or all (when not) fan control/thermal kernel modules and loading them
+# in a hook.
+#
+# While this is not strictly necessary for all kernels, particularly
+# modular kernels will not autoload those drivers, even once the full
+# system is up, which results in the fans spinning up to 100%; this is
+# particularly annoying on live systems, where the system takes a while
+# to load, so it's best to load the drivers early in initramfs stage.
+#
+# The behavior of this is inspired by the thermal hook in Debian's
+# initramfs-tools, but written for dracut specifically and updated
+# for modern kernels (2012+).
+
+# called by dracut
+check() {
+ local _arch=${DRACUT_ARCH:-$(uname -m)}
+ # only for PowerPC Macs
+ [[ $_arch == ppc* && $_arch != ppc64le ]] || return 1
+ return 0
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ pmac_model() {
+ local pm_model
+ pm_model="$(grep model /proc/cpuinfo)"
+ echo "${pm_model##*: }"
+ }
+
+ # only PowerMac3,6 has a module, special case
+ if [[ ${DRACUT_ARCH:-$(uname -m)} != ppc64* ]]; then
+ if ! [[ $hostonly ]] || [[ "$(pmac_model)" == "PowerMac3,6" ]]; then
+ instmods therm_windtunnel
+ fi
+ return 0
+ fi
+
+ windfarm_modules() {
+ if ! [[ $hostonly ]]; then
+ # include all drivers when not hostonly
+ instmods \
+ windfarm_pm72 windfarm_pm81 windfarm_pm91 windfarm_pm112 \
+ windfarm_pm121 windfarm_rm31
+ else
+ # guess model specific module, then install the rest
+ case "$(pmac_model)" in
+ PowerMac7,2 | PowerMac7,3) instmods windfarm_pm72 ;;
+ PowerMac8,1 | PowerMac8,2) instmods windfarm_pm81 ;;
+ PowerMac9,1) instmods windfarm_pm91 ;;
+ PowerMac11,2) instmods windfarm_pm112 ;;
+ PowerMac12,1) instmods windfarm_pm121 ;;
+ RackMac3,1) instmods windfarm_rm31 ;;
+ # no match, so skip installation of the rest
+ *) return 1 ;;
+ esac
+ fi
+ return 0
+ }
+
+ # hostonly and didn't match a model; skip installing other modules
+ windfarm_modules || return 0
+ # these are all required by the assorted windfarm_pm*
+ instmods \
+ windfarm_core windfarm_cpufreq_clamp windfarm_pid \
+ windfarm_smu_controls windfarm_smu_sat windfarm_smu_sensors \
+ windfarm_fcu_controls windfarm_ad7417_sensor windfarm_max6690_sensor \
+ windfarm_lm75_sensor windfarm_lm87_sensor
+}
+
+# called by dracut
+install() {
+ # this will attempt to load the appropriate modules
+ inst_hook pre-udev 99 "$moddir/load-thermal.sh"
+}
diff --git a/modules.d/90qemu-net/module-setup.sh b/modules.d/90qemu-net/module-setup.sh
new file mode 100755
index 0000000..0fa49aa
--- /dev/null
+++ b/modules.d/90qemu-net/module-setup.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ if [[ $hostonly ]]; then
+ return 255
+ fi
+
+ if [[ $mount_needs ]]; then
+ is_qemu_virtualized && return 0
+ return 255
+ fi
+
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ # qemu specific modules
+ hostonly=$(optional_hostonly) instmods virtio_net e1000 8139cp pcnet32 e100 ne2k_pci
+}
diff --git a/modules.d/90qemu/module-setup.sh b/modules.d/90qemu/module-setup.sh
new file mode 100755
index 0000000..d11f377
--- /dev/null
+++ b/modules.d/90qemu/module-setup.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ if [[ $hostonly ]] || [[ $mount_needs ]]; then
+ is_qemu_virtualized && return 0
+ return 255
+ fi
+
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ # qemu specific modules
+ hostonly='' instmods \
+ ata_piix ata_generic pata_acpi cdrom sr_mod ahci \
+ virtio_blk virtio virtio_ring virtio_pci \
+ virtio_scsi virtio_console virtio_rng virtio_mem \
+ spapr-vscsi \
+ qemu_fw_cfg \
+ efi_secret
+}
diff --git a/modules.d/91crypt-gpg/README b/modules.d/91crypt-gpg/README
new file mode 100644
index 0000000..be6df55
--- /dev/null
+++ b/modules.d/91crypt-gpg/README
@@ -0,0 +1,50 @@
+# Directions for changing a system from password-based gpg keyfile
+# to smartcard-based gpg keyfile
+
+# Be sure that you meet the following requirements:
+# 1. GnuPG >= 2.1 installed with
+# * Smartcard support enabled (scdaemon must be built)
+# * Direct CCID access built into scdaemon
+# 2. A password-based gpg keyfile ${KEYFILE} (e.g. "keyfile.gpg"):
+# That is, a file containing the slot key for LUKS, which
+# has been encrypted symmetrically with GnuPG using
+# a password.
+# 3. Your public OpenPGP identity ${RECIPIENT} (e.g. "3A696356")
+# 4. An OpenPGP smartcard holding the decryption key associated
+# with your public identity
+# 5. A CCID smartcard reader
+
+# Notes: Requirement 4. and 5. can of course be one device, e.g.
+# a USB token with an integrated OpenPGP smartcard
+
+# Make a backup of your keyfile (assuming it lies on the boot partition)
+$ cp /boot/${KEYFILE} /safe/place/keyfile.bak.gpg
+
+# Change your keyfile from purely password-based to both
+# password-based and key-based (you can then decrypt the keyfile
+# with either method). As an example aes256 is chosen, the cipher
+# is not important to this guide, but do note that your kernel
+# must support it at boot time (be it built into the kernel image
+# or loaded as a module from the initramfs).
+$ cat /safe/place/keyfile.bak.gpg | gpg -d | gpg --encrypt --recipient ${RECIPIENT} --cipher-algo aes256 --armor -c > /safe/place/keyfile_sc.gpg
+
+# Verify that you can decrypt your new keyfile both with the password
+# and your smartcard.
+# (with smartcard inserted, you should be prompted for your PIN, unless
+# you already did so and have not yet timed out)
+$ gpg -d /safe/place/keyfile_sc.gpg
+# (with smartcard disconnected, you should be prompted for your password)
+$ gpg -d /safe/place/keyfile_sc.gpg
+
+# After verification, replace your old keyfile with your new one
+$ su -c 'cp /safe/place/keyfile_sc.gpg /boot/${KEYFILE}'
+
+# Export your public key to where crypt-gpg can find it
+$ gpg --armor --export-options export-minimal --export ${RECIPIENT} > /safe/place/crypt-public-key.gpg
+$ su -c 'cp /safe/place/crypt-public-key.gpg /etc/dracut.conf.d/crypt-public-key.gpg'
+
+# Rebuild your initramfs as usual
+# When booting with any of the requirements not met, crypt-gpg will default to password-based keyfile unlocking.
+# If all requirements are met and smartcard support is not disabled by setting the kernel option "rd.luks.smartcard=0"
+# crypt-gpg will try find and use a connected OpenPGP smartcard by prompting you for the PIN and then
+# unlocking the gpg keyfile with the smartcard.
diff --git a/modules.d/91crypt-gpg/crypt-gpg-lib.sh b/modules.d/91crypt-gpg/crypt-gpg-lib.sh
new file mode 100755
index 0000000..538419f
--- /dev/null
+++ b/modules.d/91crypt-gpg/crypt-gpg-lib.sh
@@ -0,0 +1,68 @@
+#!/bin/sh
+
+command -v ask_for_password > /dev/null || . /lib/dracut-crypt-lib.sh
+
+# gpg_decrypt mnt_point keypath keydev device
+#
+# Decrypts symmetrically encrypted (password or OpenPGP smartcard) key to standard output.
+#
+# mnt_point - mount point where <keydev> is already mounted
+# keypath - GPG encrypted key path relative to <mnt_point>
+# keydev - device on which key resides; only to display in prompt
+# device - device to be opened by cryptsetup; only to display in prompt
+gpg_decrypt() {
+ local mntp="$1"
+ local keypath="$2"
+ local keydev="$3"
+ local device="$4"
+
+ local gpghome=/tmp/gnupg
+ local opts="--homedir $gpghome --no-mdc-warning --skip-verify --quiet"
+ opts="$opts --logger-file /dev/null --batch --no-tty --passphrase-fd 0"
+
+ mkdir -m 0700 -p "$gpghome"
+
+ # Setup GnuPG home and gpg-agent for usage of OpenPGP smartcard.
+ # This requires GnuPG >= 2.1, as it uses the new ,,pinentry-mode´´
+ # feature, which - when set to ,,loopback´´ - allows us to pipe
+ # the smartcard's pin to GnuPG (instead of using a normal pinentry
+ # program needed with GnuPG < 2.1), making for uncomplicated
+ # integration with the existing codebase.
+ local useSmartcard="0"
+ local gpgMajorVersion
+ local gpgMinorVersion
+ local cmd
+ gpgMajorVersion="$(gpg --version | sed -n 1p | sed -n -r -e 's|.* ([0-9]*).*|\1|p')"
+ gpgMinorVersion="$(gpg --version | sed -n 1p | sed -n -r -e 's|.* [0-9]*\.([0-9]*).*|\1|p')"
+
+ if [ "${gpgMajorVersion}" -ge 2 ] && [ "${gpgMinorVersion}" -ge 1 ] \
+ && [ -f /root/crypt-public-key.gpg ] && getargbool 1 rd.luks.smartcard; then
+ useSmartcard="1"
+ echo "allow-loopback-pinentry" >> "$gpghome/gpg-agent.conf"
+ GNUPGHOME="$gpghome" gpg-agent --quiet --daemon
+ GNUPGHOME="$gpghome" gpg --quiet --no-tty --import < /root/crypt-public-key.gpg
+ local smartcardSerialNumber
+ smartcardSerialNumber="$(GNUPGHOME=$gpghome gpg --no-tty --card-status \
+ | sed -n -r -e 's|Serial number.*: ([0-9]*)|\1|p' | tr -d '\n')"
+ if [ -n "${smartcardSerialNumber}" ]; then
+ inputPrompt="PIN (OpenPGP card ${smartcardSerialNumber})"
+ fi
+ GNUPGHOME="$gpghome" gpg-connect-agent 1> /dev/null learn /bye
+ opts="$opts --pinentry-mode=loopback"
+ cmd="GNUPGHOME=$gpghome gpg --card-status --no-tty > /dev/null 2>&1; gpg $opts --decrypt $mntp/$keypath"
+ else
+ cmd="gpg $opts --decrypt $mntp/$keypath"
+ fi
+
+ ask_for_password \
+ --cmd "$cmd" \
+ --prompt "${inputPrompt:-Password ($keypath on $keydev for $device)}" \
+ --tries 3 --tty-echo-off
+
+ # Clean up the smartcard gpg-agent
+ if [ "${useSmartcard}" = "1" ]; then
+ GNUPGHOME="$gpghome" gpg-connect-agent 1> /dev/null killagent /bye
+ fi
+
+ rm -rf -- "$gpghome"
+}
diff --git a/modules.d/91crypt-gpg/module-setup.sh b/modules.d/91crypt-gpg/module-setup.sh
new file mode 100755
index 0000000..501869a
--- /dev/null
+++ b/modules.d/91crypt-gpg/module-setup.sh
@@ -0,0 +1,73 @@
+#!/bin/bash
+
+# GPG support is optional
+# called by dracut
+check() {
+ require_binaries gpg tr || return 1
+
+ if sc_requested; then
+ if ! sc_supported; then
+ dwarning "crypt-gpg: GnuPG >= 2.1 with scdaemon and libusb required for ccid smartcard support"
+ return 1
+ fi
+ return 0
+ fi
+
+ return 255
+}
+
+# called by dracut
+depends() {
+ echo crypt
+}
+
+# called by dracut
+install() {
+ inst_multiple gpg tr
+ inst "$moddir/crypt-gpg-lib.sh" "/lib/dracut-crypt-gpg-lib.sh"
+
+ if sc_requested; then
+ inst_multiple gpg-agent
+ inst_multiple gpg-connect-agent
+ inst_multiple -o /usr/libexec/scdaemon /usr/lib/gnupg/scdaemon
+ cp "$dracutsysrootdir$(sc_public_key)" "${initdir}/root/"
+ fi
+}
+
+sc_public_key() {
+ echo -n "/etc/dracut.conf.d/crypt-public-key.gpg"
+}
+
+# CCID Smartcard support requires GnuPG >= 2.1 with scdaemon and libusb
+sc_supported() {
+ local gpgMajor
+ local gpgMinor
+ local scdaemon
+ gpgMajor="$(gpg --version | sed -n 1p | sed -n -r -e 's|.* ([0-9]*).*|\1|p')"
+ gpgMinor="$(gpg --version | sed -n 1p | sed -n -r -e 's|.* [0-9]*\.([0-9]*).*|\1|p')"
+
+ if [[ -x "$dracutsysrootdir"/usr/libexec/scdaemon ]]; then
+ scdaemon=/usr/libexec/scdaemon
+ elif [[ -x "$dracutsysrootdir"/usr/lib/gnupg/scdaemon ]]; then
+ scdaemon=/usr/lib/gnupg/scdaemon
+ else
+ return 1
+ fi
+
+ if [[ ${gpgMajor} -gt 2 || ${gpgMajor} -eq 2 && ${gpgMinor} -ge 1 ]] \
+ && require_binaries gpg-agent \
+ && require_binaries gpg-connect-agent \
+ && ($DRACUT_LDD "${dracutsysrootdir}${scdaemon}" | grep libusb > /dev/null); then
+ return 0
+ else
+ return 1
+ fi
+}
+
+sc_requested() {
+ if [ -f "$dracutsysrootdir$(sc_public_key)" ]; then
+ return 0
+ else
+ return 1
+ fi
+}
diff --git a/modules.d/91crypt-loop/crypt-loop-lib.sh b/modules.d/91crypt-loop/crypt-loop-lib.sh
new file mode 100755
index 0000000..7db82e2
--- /dev/null
+++ b/modules.d/91crypt-loop/crypt-loop-lib.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+command -v ask_for_password > /dev/null || . /lib/dracut-crypt-lib.sh
+
+# loop_decrypt mnt_point keypath keydev device
+#
+# Decrypts symmetrically encrypted key to standard output.
+#
+# mnt_point - mount point where <keydev> is already mounted
+# keypath - LUKS encrypted loop file path relative to <mnt_point>
+# keydev - device on which key resides; only to display in prompt
+# device - device to be opened by cryptsetup; only to display in prompt
+loop_decrypt() {
+ local mntp="$1"
+ local keypath="$2"
+ local keydev="$3"
+ local device="$4"
+ local key
+
+ key="/dev/mapper/$(str_replace "loop-$keydev-$mntp-$keypath" '/' '-')"
+
+ if [ ! -b "$key" ]; then
+ local loopdev
+ local opts
+ loopdev=$(losetup -f "${mntp}/${keypath}" --show)
+ opts="-d - luksOpen $loopdev ${key##*/}"
+
+ ask_for_password \
+ --cmd "cryptsetup $opts" \
+ --prompt "Password ($keypath on $keydev for $device)" \
+ --tty-echo-off
+
+ [ -b "$key" ] || die "Failed to unlock $keypath on $keydev for $device."
+
+ printf "%s\n" "cryptsetup luksClose \"$key\"" > "${hookdir}/cleanup/crypt-loop-cleanup-10-${key##*/}.sh"
+ printf "%s\n" "losetup -d \"$loopdev\"" > "${hookdir}/cleanup/crypt-loop-cleanup-20-${loopdev##*/}.sh"
+ fi
+
+ cat "$key"
+}
diff --git a/modules.d/91crypt-loop/module-setup.sh b/modules.d/91crypt-loop/module-setup.sh
new file mode 100755
index 0000000..ff0d501
--- /dev/null
+++ b/modules.d/91crypt-loop/module-setup.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ require_binaries losetup || return 1
+
+ return 255
+}
+
+# called by dracut
+depends() {
+ echo crypt
+}
+
+# called by dracut
+installkernel() {
+ hostonly='' instmods loop
+}
+
+# called by dracut
+install() {
+ inst_multiple losetup
+ inst "$moddir/crypt-loop-lib.sh" "/lib/dracut-crypt-loop-lib.sh"
+ dracut_need_initqueue
+}
diff --git a/modules.d/91fido2/module-setup.sh b/modules.d/91fido2/module-setup.sh
new file mode 100755
index 0000000..def7a0f
--- /dev/null
+++ b/modules.d/91fido2/module-setup.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+}
+
+# Module dependency requirements.
+depends() {
+ # This module has external dependency on other module(s).
+ echo systemd-udevd
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+ # Install required libraries.
+ _arch=${DRACUT_ARCH:-$(uname -m)}
+ inst_libdir_file \
+ {"tls/$_arch/",tls/,"$_arch/",}"libfido2.so.*" \
+ {"tls/$_arch/",tls/,"$_arch/",}"libz.so.*" \
+ {"tls/$_arch/",tls/,"$_arch/",}"libcryptsetup.so.*" \
+ {"tls/$_arch/",tls/,"$_arch/",}"/cryptsetup/libcryptsetup-token-systemd-fido2.so" \
+ {"tls/$_arch/",tls/,"$_arch/",}"libcbor.so.*" \
+ {"tls/$_arch/",tls/,"$_arch/",}"libhidapi-hidraw.so.*"
+}
diff --git a/modules.d/91pcsc/module-setup.sh b/modules.d/91pcsc/module-setup.sh
new file mode 100755
index 0000000..6f8b2c8
--- /dev/null
+++ b/modules.d/91pcsc/module-setup.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed.
+ require_binaries pcscd || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # This module has external dependency on other module(s).
+ echo systemd-udevd
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+ inst_simple "$moddir/pcscd.service" "${systemdsystemunitdir}"/pcscd.service
+ inst_simple "$moddir/pcscd.socket" "${systemdsystemunitdir}"/pcscd.socket
+
+ inst_multiple -o \
+ pcscd
+
+ # Enable systemd type unit(s)
+ for i in \
+ pcscd.service \
+ pcscd.socket; do
+ $SYSTEMCTL -q --root "$initdir" enable "$i"
+ done
+
+ # Install library file(s)
+ _arch=${DRACUT_ARCH:-$(uname -m)}
+ inst_libdir_file \
+ {"tls/$_arch/",tls/,"$_arch/",}"libopensc.so.*" \
+ {"tls/$_arch/",tls/,"$_arch/",}"libsmm-local.so.*" \
+ {"tls/$_arch/",tls/,"$_arch/",}"opensc-pkcs11.so" \
+ {"tls/$_arch/",tls/,"$_arch/",}"onepin-opensc-pkcs11.so" \
+ {"tls/$_arch/",tls/,"$_arch/",}"pkcs11/opensc-pkcs11.so" \
+ {"tls/$_arch/",tls/,"$_arch/",}"pkcs11/onepin-opensc-pkcs11.so" \
+ {"tls/$_arch/",tls/,"$_arch/",}"pcsc/drivers/ifd-ccid.bundle/Contents/Info.plist" \
+ {"tls/$_arch/",tls/,"$_arch/",}"pcsc/drivers/ifd-ccid.bundle/Contents/Linux/libccid.so" \
+ {"tls/$_arch/",tls/,"$_arch/",}"pcsc/drivers/serial/libccidtwin.so" \
+ {"tls/$_arch/",tls/,"$_arch/",}"libpcsclite.so.*"
+
+ # Install the hosts local user configurations if enabled.
+ if [[ $hostonly ]]; then
+ inst_multiple -H -o \
+ /etc/opensc.conf \
+ "/etc/reader.conf.d/*"
+ fi
+
+}
diff --git a/modules.d/91pcsc/pcscd.service b/modules.d/91pcsc/pcscd.service
new file mode 100644
index 0000000..639decd
--- /dev/null
+++ b/modules.d/91pcsc/pcscd.service
@@ -0,0 +1,13 @@
+[Unit]
+DefaultDependencies=no
+Description=PC/SC Smart Card Daemon (Dracut)
+Documentation=man:pcscd(8)
+Requires=pcscd.socket
+
+[Service]
+ExecStart=/usr/sbin/pcscd --foreground --auto-exit
+ExecReload=/usr/sbin/pcscd --hotplug
+
+[Install]
+Also=pcscd.socket
+WantedBy=cryptsetup-pre.target
diff --git a/modules.d/91pcsc/pcscd.socket b/modules.d/91pcsc/pcscd.socket
new file mode 100644
index 0000000..b20dd5a
--- /dev/null
+++ b/modules.d/91pcsc/pcscd.socket
@@ -0,0 +1,11 @@
+[Unit]
+DefaultDependencies=no
+Description=PC/SC Smart Card Daemon Activation Socket (Dracut)
+Documentation=man:pcscd(8)
+
+[Socket]
+ListenStream=/run/pcscd/pcscd.comm
+SocketMode=0666
+
+[Install]
+WantedBy=cryptsetup-pre.target sockets.target
diff --git a/modules.d/91pkcs11/module-setup.sh b/modules.d/91pkcs11/module-setup.sh
new file mode 100755
index 0000000..5675efb
--- /dev/null
+++ b/modules.d/91pkcs11/module-setup.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # This module has external dependency on other module(s).
+ echo systemd-udevd
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+
+ # Install library file(s)
+ _arch=${DRACUT_ARCH:-$(uname -m)}
+ inst_libdir_file \
+ {"tls/$_arch/",tls/,"$_arch/",}"libtasn1.so.*" \
+ {"tls/$_arch/",tls/,"$_arch/",}"libffi.so.*" \
+ {"tls/$_arch/",tls/,"$_arch/",}"libp11-kit.so.*" \
+ {"tls/$_arch/",tls/,"$_arch/",}"libcryptsetup.so.*" \
+ {"tls/$_arch/",tls/,"$_arch/",}"/cryptsetup/libcryptsetup-token-systemd-pkcs11.so*"
+
+}
diff --git a/modules.d/91tpm2-tss/module-setup.sh b/modules.d/91tpm2-tss/module-setup.sh
new file mode 100755
index 0000000..e145c41
--- /dev/null
+++ b/modules.d/91tpm2-tss/module-setup.sh
@@ -0,0 +1,59 @@
+#!/bin/bash
+# This file is part of dracut.
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Prerequisite check(s) for module.
+check() {
+
+ # If the binary(s) requirements are not fulfilled the module can't be installed.
+ require_binaries tpm2 || return 1
+
+ # Return 255 to only include the module, if another module requires it.
+ return 255
+
+}
+
+# Module dependency requirements.
+depends() {
+
+ # This module has external dependency on other module(s).
+ echo systemd-sysusers systemd-udevd
+ # Return 0 to include the dependent module(s) in the initramfs.
+ return 0
+
+}
+
+# Install kernel module(s).
+installkernel() {
+ instmods '=drivers/char/tpm'
+}
+
+# Install the required file(s) and directories for the module in the initramfs.
+install() {
+
+ inst_multiple -o \
+ "$sysusers"/tpm2-tss.conf \
+ "$tmpfilesdir"/tpm2-tss-fapi.conf \
+ "$udevrulesdir"/60-tpm-udev.rules \
+ tpm2_pcrread tpm2_pcrextend tpm2_createprimary tpm2_createpolicy \
+ tpm2_create tpm2_load tpm2_unseal tpm2
+
+ # Install library file(s)
+ _arch=${DRACUT_ARCH:-$(uname -m)}
+ inst_libdir_file \
+ {"tls/$_arch/",tls/,"$_arch/",}"libtss2-esys.so.*" \
+ {"tls/$_arch/",tls/,"$_arch/",}"libtss2-fapi.so.*" \
+ {"tls/$_arch/",tls/,"$_arch/",}"libtss2-mu.so.*" \
+ {"tls/$_arch/",tls/,"$_arch/",}"libtss2-rc.so.*" \
+ {"tls/$_arch/",tls/,"$_arch/",}"libtss2-sys.so.*" \
+ {"tls/$_arch/",tls/,"$_arch/",}"libtss2-tcti-cmd.so.*" \
+ {"tls/$_arch/",tls/,"$_arch/",}"libtss2-tcti-device.so.*" \
+ {"tls/$_arch/",tls/,"$_arch/",}"libtss2-tcti-mssim.so.*" \
+ {"tls/$_arch/",tls/,"$_arch/",}"libtss2-tcti-swtpm.so.*" \
+ {"tls/$_arch/",tls/,"$_arch/",}"libtss2-tctildr.so.*" \
+ {"tls/$_arch/",tls/,"$_arch/",}"libcryptsetup.so.*" \
+ {"tls/$_arch/",tls/,"$_arch/",}"/cryptsetup/libcryptsetup-token-systemd-tpm2.so" \
+ {"tls/$_arch/",tls/,"$_arch/",}"libcurl.so.*" \
+ {"tls/$_arch/",tls/,"$_arch/",}"libjson-c.so.*"
+
+}
diff --git a/modules.d/91zipl/install_zipl_cmdline.sh b/modules.d/91zipl/install_zipl_cmdline.sh
new file mode 100755
index 0000000..9332d31
--- /dev/null
+++ b/modules.d/91zipl/install_zipl_cmdline.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+DEV="$1"
+MNT=/boot/zipl
+
+if [ -z "$DEV" ]; then
+ echo "No IPL device given"
+ : > /tmp/install.zipl.cmdline-done
+ exit 1
+fi
+
+[ -d ${MNT} ] || mkdir -p ${MNT}
+
+if ! mount -o ro "${DEV}" ${MNT}; then
+ echo "Failed to mount ${MNT}"
+ : > /tmp/install.zipl.cmdline-done
+ exit 1
+fi
+
+if [ -f ${MNT}/dracut-cmdline.conf ]; then
+ cp ${MNT}/dracut-cmdline.conf /etc/cmdline.d/99zipl.conf
+fi
+
+if [ -f ${MNT}/active_devices.txt ]; then
+ while read -r dev _ || [[ $dev ]]; do
+ [ "$dev" = "#" -o "$dev" = "" ] && continue
+ cio_ignore -r "$dev"
+ done < ${MNT}/active_devices.txt
+fi
+
+umount ${MNT}
+
+if [ -f /etc/cmdline.d/99zipl.conf ]; then
+ systemctl restart dracut-cmdline.service
+ systemctl restart systemd-udev-trigger.service
+fi
+: > /tmp/install.zipl.cmdline-done
+
+exit 0
diff --git a/modules.d/91zipl/module-setup.sh b/modules.d/91zipl/module-setup.sh
new file mode 100755
index 0000000..cb21454
--- /dev/null
+++ b/modules.d/91zipl/module-setup.sh
@@ -0,0 +1,67 @@
+#!/bin/bash
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+
+get_boot_zipl_dev() {
+ local _boot_zipl
+ _boot_zipl=$(sed -n -e '/^[[:space:]]*#/d' -e 's/\(.*\)\w*\/boot\/zipl.*/\1/p' "$dracutsysrootdir"/etc/fstab)
+ printf "%s" "$(trim "$_boot_zipl")"
+}
+
+# called by dracut
+check() {
+ local _arch=${DRACUT_ARCH:-$(uname -m)}
+ # Only for systems on s390 using indirect booting via userland grub
+ [ "$_arch" = "s390" -o "$_arch" = "s390x" ] || return 1
+ # /boot/zipl contains a first stage kernel used to launch grub in initrd
+ [ -d /boot/zipl ] || return 1
+ return 0
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ local _boot_zipl
+
+ _boot_zipl=$(get_boot_zipl_dev)
+ if [ -n "$_boot_zipl" ]; then
+ eval "$(blkid -s TYPE -o udev "${_boot_zipl}")"
+ if [ -n "$ID_FS_TYPE" ]; then
+ case "$ID_FS_TYPE" in
+ ext?)
+ ID_FS_TYPE=ext4
+ ;;
+ esac
+ instmods ${ID_FS_TYPE}
+ fi
+ fi
+}
+
+# called by dracut
+cmdline() {
+ local _boot_zipl
+
+ _boot_zipl=$(get_boot_zipl_dev)
+ if [ -n "$_boot_zipl" ]; then
+ printf "%s" " rd.zipl=${_boot_zipl}"
+ fi
+}
+
+# called by dracut
+install() {
+ inst_multiple mount umount
+
+ inst_hook cmdline 91 "$moddir/parse-zipl.sh"
+ inst_script "${moddir}/install_zipl_cmdline.sh" /sbin/install_zipl_cmdline.sh
+ if [[ $hostonly_cmdline == "yes" ]]; then
+ local _zipl
+ _zipl=$(cmdline)
+
+ [[ $_zipl ]] && printf "%s\n" "$_zipl" > "${initdir}/etc/cmdline.d/91zipl.conf"
+ fi
+ dracut_need_initqueue
+}
diff --git a/modules.d/91zipl/parse-zipl.sh b/modules.d/91zipl/parse-zipl.sh
new file mode 100755
index 0000000..d95a1dd
--- /dev/null
+++ b/modules.d/91zipl/parse-zipl.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+
+zipl_arg=$(getarg rd.zipl)
+
+if [ -n "$zipl_arg" ]; then
+ case "$zipl_arg" in
+ LABEL=*)
+ zipl_env="ENV{ID_FS_LABEL}"
+ zipl_val=${zipl_arg#LABEL=}
+ zipl_arg="$(label_uuid_to_dev "${zipl_val}")"
+ ;;
+ UUID=*)
+ zipl_env="ENV{ID_FS_UUID}"
+ zipl_val=${zipl_arg#UUID=}
+ zipl_arg="$(label_uuid_to_dev "${zipl_val}")"
+ ;;
+ PARTLABEL=*)
+ zipl_env="ENV{ID_FS_PARTLABEL}"
+ zipl_val=${zipl_arg#PARTLABEL=}
+ zipl_arg="$(label_uuid_to_dev "${zipl_val}")"
+ ;;
+ PARTUUID=*)
+ zipl_env="ENV{ID_FS_PARTUUID}"
+ zipl_val=${zipl_arg#PARTUUID=}
+ zipl_arg="$(label_uuid_to_dev "${zipl_val}")"
+ ;;
+ /dev/mapper/*)
+ zipl_env="ENV{DM_NAME}"
+ zipl_val=${zipl_arg#/dev/mapper/}
+ ;;
+ /dev/disk/by-*)
+ zipl_env="SYMLINK"
+ zipl_val=${zipl_arg#/dev/}
+ ;;
+ /dev/*)
+ zipl_env="KERNEL"
+ zipl_val=${zipl_arg}
+ ;;
+ esac
+ if [ "$zipl_env" ]; then
+ {
+ printf 'ACTION=="add|change", SUBSYSTEM=="block", %s=="%s", ENV{SYSTEMD_READY}!="0", RUN+="/sbin/initqueue --settled --onetime --unique --name install_zipl_cmdline /sbin/install_zipl_cmdline.sh %s"\n' \
+ ${zipl_env} "${zipl_val}" "${zipl_arg}"
+ echo "[ -f /tmp/install.zipl.cmdline-done ]" > "$hookdir"/initqueue/finished/wait-zipl-conf.sh
+ } >> /etc/udev/rules.d/99zipl-conf.rules
+ cat /etc/udev/rules.d/99zipl-conf.rules
+ fi
+ wait_for_dev -n "$zipl_arg"
+fi
diff --git a/modules.d/95cifs/cifs-lib.sh b/modules.d/95cifs/cifs-lib.sh
new file mode 100755
index 0000000..b996b41
--- /dev/null
+++ b/modules.d/95cifs/cifs-lib.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+# cifs_to_var CIFSROOT
+# use CIFSROOT to set $server, $path, and $options.
+# CIFSROOT is something like: cifs://[<username>[:<password>]]@<host>/<path>
+# NETIF is used to get information from DHCP options, if needed.
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+cifs_to_var() {
+ local cifsuser
+ local cifspass
+ # Check required arguments
+ server=${1##cifs://}
+ cifsuser=${server%@*}
+ cifspass=${cifsuser#*:}
+ if [ "$cifspass" != "$cifsuser" ]; then
+ cifsuser=${cifsuser%:*}
+ else
+ cifspass=$(getarg cifspass)
+ fi
+ if [ "$cifsuser" != "$server" ]; then
+ server="${server#*@}"
+ else
+ cifsuser=$(getarg cifsuser)
+ fi
+
+ # shellcheck disable=SC2034
+ path=${server#*/}
+ # shellcheck disable=SC2034
+ server=${server%/*}
+
+ if [ ! "$cifsuser" -o ! "$cifspass" ]; then
+ die "For CIFS support you need to specify a cifsuser and cifspass either in the cifsuser and cifspass commandline parameters or in the root= CIFS URL."
+ fi
+ # shellcheck disable=SC2034
+ options="user=$cifsuser,pass=$cifspass,$(getarg rootflags=)"
+}
diff --git a/modules.d/95cifs/cifsroot.sh b/modules.d/95cifs/cifsroot.sh
new file mode 100755
index 0000000..83539d4
--- /dev/null
+++ b/modules.d/95cifs/cifsroot.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+. /lib/cifs-lib.sh
+
+[ "$#" = 3 ] || exit 1
+
+# root is in the form root=cifs://user:pass@[server]/[folder] either from
+# cmdline or dhcp root-path
+#netif="$1"
+root="$2"
+NEWROOT="$3"
+
+cifs_to_var "$root"
+
+mount.cifs "//$server/$path" "$NEWROOT" -o "$options" && { [ -e /dev/root ] || ln -s null /dev/root; }
+
+# inject new exit_if_exists
+# shellcheck disable=SC2016
+echo 'settle_exit_if_exists="--exit-if-exists=/dev/root"; rm -f -- "$job"' > "$hookdir"/initqueue/cifs.sh
+# force udevsettle to break
+: > "$hookdir"/initqueue/work
diff --git a/modules.d/95cifs/module-setup.sh b/modules.d/95cifs/module-setup.sh
new file mode 100755
index 0000000..6abc475
--- /dev/null
+++ b/modules.d/95cifs/module-setup.sh
@@ -0,0 +1,58 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ # If our prerequisites are not met, fail anyways.
+ require_binaries mount.cifs || return 1
+
+ [[ $hostonly ]] || [[ $mount_needs ]] && {
+ for fs in "${host_fs_types[@]}"; do
+ [[ $fs == "cifs" ]] && return 0
+ done
+ return 255
+ }
+
+ return 0
+}
+
+# called by dracut
+depends() {
+ # We depend on network modules being loaded
+ echo network
+}
+
+# called by dracut
+installkernel() {
+ instmods cifs ipv6
+ # hash algos
+ instmods md4 md5 sha256 sha512
+ # ciphers
+ instmods aes arc4 des ecb gcm aead2
+ # macs
+ instmods hmac cmac ccm
+}
+
+# called by dracut
+install() {
+ local _nsslibs
+ inst_multiple -o mount.cifs
+ inst_multiple -o /etc/services /etc/nsswitch.conf /etc/protocols
+ inst_multiple -o /usr/etc/services /usr/etc/nsswitch.conf /usr/etc/protocols
+
+ inst_libdir_file 'libcap-ng.so*'
+
+ _nsslibs=$(
+ cat "$dracutsysrootdir"/{,usr/}etc/nsswitch.conf 2> /dev/null \
+ | sed -e '/^#/d' -e 's/^.*://' -e 's/\[NOTFOUND=return\]//' \
+ | tr -s '[:space:]' '\n' | sort -u | tr -s '[:space:]' '|'
+ )
+ _nsslibs=${_nsslibs#|}
+ _nsslibs=${_nsslibs%|}
+
+ inst_libdir_file -n "$_nsslibs" 'libnss_*.so*'
+
+ inst_hook cmdline 90 "$moddir/parse-cifsroot.sh"
+ inst "$moddir/cifsroot.sh" "/sbin/cifsroot"
+ inst "$moddir/cifs-lib.sh" "/lib/cifs-lib.sh"
+ dracut_need_initqueue
+}
diff --git a/modules.d/95cifs/parse-cifsroot.sh b/modules.d/95cifs/parse-cifsroot.sh
new file mode 100755
index 0000000..b88bef4
--- /dev/null
+++ b/modules.d/95cifs/parse-cifsroot.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+#
+# root=cifs://[user:pass@]<server>/<folder>
+#
+# This syntax can come from DHCP root-path as well.
+#
+# If a username or password are not specified as part of the root, then they
+# will be pulled from cifsuser and cifspass on the kernel command line,
+# respectively.
+#
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+. /lib/cifs-lib.sh
+
+# This script is sourced, so root should be set. But let's be paranoid
+[ -z "$root" ] && root=$(getarg root=)
+
+if [ -z "$netroot" ]; then
+ for netroot in $(getargs netroot=); do
+ [ "${netroot%%:*}" = "cifs" ] && break
+ done
+ [ "${netroot%%:*}" = "cifs" ] || unset netroot
+fi
+
+# Root takes precedence over netroot
+if [ "${root%%:*}" = "cifs" ]; then
+ if [ -n "$netroot" ]; then
+ warn "root takes precedence over netroot. Ignoring netroot"
+ fi
+ netroot=$root
+ unset root
+fi
+
+# If it's not cifs we don't continue
+[ "${netroot%%:*}" = "cifs" ] || return
+
+# Check required arguments
+cifs_to_var "$netroot"
+
+# If we don't have a server, we need dhcp
+if [ -z "$server" ]; then
+ # shellcheck disable=SC2034
+ DHCPORSERVER="1"
+fi
+
+# Done, all good!
+# shellcheck disable=SC2034
+rootok=1
+
+# shellcheck disable=SC2016
+echo '[ -e $NEWROOT/proc ]' > "$hookdir"/initqueue/finished/cifsroot.sh
diff --git a/modules.d/95dasd/module-setup.sh b/modules.d/95dasd/module-setup.sh
new file mode 100755
index 0000000..180da14
--- /dev/null
+++ b/modules.d/95dasd/module-setup.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ local _arch=${DRACUT_ARCH:-$(uname -m)}
+ [ "$_arch" = "s390" -o "$_arch" = "s390x" ] || return 1
+ require_binaries normalize_dasd_arg || return 1
+ return 0
+}
+
+# called by dracut
+depends() {
+ echo "dasd_mod"
+ return 0
+}
+
+# called by dracut
+install() {
+ inst_hook cmdline 30 "$moddir/parse-dasd.sh"
+ inst_multiple dasdinfo dasdconf.sh normalize_dasd_arg
+ conf=/etc/dasd.conf
+ if [[ $hostonly && -f $conf ]]; then
+ inst -H $conf
+ fi
+ inst_rules 56-dasd.rules
+ inst_rules 59-dasd.rules
+}
diff --git a/modules.d/95dasd/parse-dasd.sh b/modules.d/95dasd/parse-dasd.sh
new file mode 100755
index 0000000..cda3970
--- /dev/null
+++ b/modules.d/95dasd/parse-dasd.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+for dasd_arg in $(getargs rd.dasd= -d rd_DASD= DASD=); do
+ (
+ local OLDIFS="$IFS"
+ IFS=","
+ # shellcheck disable=SC2086
+ set -- $dasd_arg
+ IFS="$OLDIFS"
+ echo "$@" | normalize_dasd_arg >> /etc/dasd.conf
+ )
+done
diff --git a/modules.d/95dasd_mod/module-setup.sh b/modules.d/95dasd_mod/module-setup.sh
new file mode 100755
index 0000000..c59dd3a
--- /dev/null
+++ b/modules.d/95dasd_mod/module-setup.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ local _arch=${DRACUT_ARCH:-$(uname -m)}
+ [ "$_arch" = "s390" -o "$_arch" = "s390x" ] || return 1
+ require_binaries grep sed seq
+
+ return 0
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ instmods dasd_mod dasd_eckd_mod dasd_fba_mod dasd_diag_mod
+}
+
+# called by dracut
+install() {
+ inst_hook cmdline 31 "$moddir/parse-dasd-mod.sh"
+ inst_multiple grep sed seq
+ inst_multiple -o dasd_cio_free
+}
diff --git a/modules.d/95dasd_mod/parse-dasd-mod.sh b/modules.d/95dasd_mod/parse-dasd-mod.sh
new file mode 100755
index 0000000..2b86d45
--- /dev/null
+++ b/modules.d/95dasd_mod/parse-dasd-mod.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+mod_args=""
+
+for dasd_arg in $(getargs rd.dasd= -d rd_DASD= DASD=); do
+ mod_args="$mod_args,$dasd_arg"
+done
+
+mod_args="${mod_args#*,}"
+
+if [ -x /sbin/dasd_cio_free -a -n "$mod_args" ]; then
+ [ -d /etc/modprobe.d ] || mkdir -m 0755 -p /etc/modprobe.d
+ echo "options dasd_mod dasd=$mod_args" >> /etc/modprobe.d/dasd_mod.conf
+fi
+
+unset dasd_arg
+if [ -x /sbin/dasd_cio_free ]; then
+ dasd_cio_free
+fi
diff --git a/modules.d/95dasd_rules/module-setup.sh b/modules.d/95dasd_rules/module-setup.sh
new file mode 100755
index 0000000..06c57a4
--- /dev/null
+++ b/modules.d/95dasd_rules/module-setup.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+
+# called by dracut
+cmdline() {
+ is_dasd() {
+ local _dev=$1
+ local _devpath
+ _devpath=$(
+ cd -P /sys/dev/block/"$_dev" || exit
+ echo "$PWD"
+ )
+
+ [ "${_devpath#*/dasd}" == "$_devpath" ] && return 1
+ _ccw="${_devpath%%/block/*}"
+ echo "rd.dasd=${_ccw##*/}"
+ return 0
+ }
+ [[ $hostonly ]] || [[ $mount_needs ]] && {
+ for_each_host_dev_and_slaves_all is_dasd || return 255
+ } | sort | uniq
+}
+
+# called by dracut
+check() {
+ local _arch=${DRACUT_ARCH:-$(uname -m)}
+ local found=0
+ local bdev
+ [ "$_arch" = "s390" -o "$_arch" = "s390x" ] || return 1
+
+ [[ $hostonly ]] || [[ $mount_needs ]] && {
+ for bdev in /sys/block/*; do
+ case "${bdev##*/}" in
+ dasd*)
+ found=$((found + 1))
+ break
+ ;;
+ esac
+ done
+ [ $found -eq 0 ] && return 255
+ }
+ return 0
+}
+
+# called by dracut
+depends() {
+ echo 'dasd_mod' bash
+ return 0
+}
+
+# called by dracut
+install() {
+ inst_hook cmdline 30 "$moddir/parse-dasd.sh"
+ if [[ $hostonly_cmdline == "yes" ]]; then
+ local _dasd
+ _dasd=$(cmdline)
+ [[ $_dasd ]] && printf "%s\n" "$_dasd" >> "${initdir}/etc/cmdline.d/95dasd.conf"
+ fi
+ if [[ $hostonly ]]; then
+ inst_rules_wildcard "51-dasd-*.rules"
+ inst_rules_wildcard "41-dasd-*.rules"
+ mark_hostonly /etc/udev/rules.d/51-dasd-*.rules
+ mark_hostonly /etc/udev/rules.d/41-dasd-*.rules
+ fi
+ inst_rules 59-dasd.rules
+}
diff --git a/modules.d/95dasd_rules/parse-dasd.sh b/modules.d/95dasd_rules/parse-dasd.sh
new file mode 100755
index 0000000..4454aec
--- /dev/null
+++ b/modules.d/95dasd_rules/parse-dasd.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+allow_device() {
+ local ccw=$1
+
+ if [ -x /sbin/cio_ignore ] && cio_ignore -i "$ccw" > /dev/null; then
+ cio_ignore -r "$ccw"
+ fi
+}
+
+if [[ -f /sys/firmware/ipl/ipl_type ]] && [[ $(< /sys/firmware/ipl/ipl_type) == "ccw" ]]; then
+ allow_device "$(< /sys/firmware/ipl/device)"
+fi
+
+for dasd_arg in $(getargs root=) $(getargs resume=); do
+ [[ $dasd_arg =~ /dev/disk/by-path/ccw-* ]] || continue
+
+ ccw_dev="${dasd_arg##*/ccw-}"
+ allow_device "${ccw_dev%%-*}"
+done
+
+for dasd_arg in $(getargs rd.dasd=); do
+ IFS=',' read -r -a devs <<< "$dasd_arg"
+ declare -p devs
+ for dev in "${devs[@]}"; do
+ case "$dev" in
+ autodetect | probeonly) ;;
+
+ *-*)
+ IFS="-" read -r start end _ <<< "${dev%(ro)}"
+ prefix=${start%.*}
+ start=${start##*.}
+ for rdev in $(seq $((16#$start)) $((16#$end))); do
+ allow_device "$(printf "%s.%04x" "$prefix" "$rdev")"
+ done
+ ;;
+ *)
+ IFS="." read -r sid ssid chan _ <<< "${dev%(ro)}"
+ allow_device "$(printf "%01x.%01x.%04x" $((16#$sid)) $((16#$ssid)) $((16#$chan)))"
+ ;;
+ esac
+ done
+done
diff --git a/modules.d/95dcssblk/module-setup.sh b/modules.d/95dcssblk/module-setup.sh
new file mode 100755
index 0000000..67af4ad
--- /dev/null
+++ b/modules.d/95dcssblk/module-setup.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+
+# called by dracut
+check() {
+ local _arch=${DRACUT_ARCH:-$(uname -m)}
+ [[ $_arch == "s390" ]] || [[ $_arch == "s390x" ]] || return 1
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ if [[ $hostonly ]]; then
+ for dev in /sys/devices/dcssblk/*/block/dcssblk*; do
+ [[ -e $dev ]] || continue
+ hostonly='' instmods dcssblk
+ return $?
+ done
+ else
+ hostonly='' instmods dcssblk
+ fi
+}
+
+# called by dracut
+install() {
+ inst_hook cmdline 30 "$moddir/parse-dcssblk.sh"
+ # If there is a config file which contains avail (best only of root device)
+ # disks to activate add it and use it during boot -> then we do not need
+ # a kernel param anymore
+ #if [[ $hostonly ]]; then
+ # inst /etc/dcssblk.conf
+ #fi
+}
diff --git a/modules.d/95dcssblk/parse-dcssblk.sh b/modules.d/95dcssblk/parse-dcssblk.sh
new file mode 100755
index 0000000..980160a
--- /dev/null
+++ b/modules.d/95dcssblk/parse-dcssblk.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+if dcssblk_arg=$(getarg rd.dcssblk=); then
+ info "Loading dcssblk segments=$dcssblk_arg"
+ modprobe dcssblk segments="$dcssblk_arg"
+fi
diff --git a/modules.d/95debug/module-setup.sh b/modules.d/95debug/module-setup.sh
new file mode 100755
index 0000000..3124f1a
--- /dev/null
+++ b/modules.d/95debug/module-setup.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ # do not add this module by default
+ return 255
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+# called by dracut
+install() {
+ inst_multiple -o ls ps grep more cat rm strace free showmount df du lsblk \
+ ping netstat rpcinfo vi scp ping6 ssh find chroot \
+ tcpdump cp dd less hostname mkdir systemd-analyze \
+ fsck fsck.ext2 fsck.ext4 fsck.ext3 fsck.ext4dev fsck.f2fs fsck.vfat e2fsck
+
+ grep '^tcpdump:' "$dracutsysrootdir"/etc/passwd 2> /dev/null >> "$initdir/etc/passwd"
+}
diff --git a/modules.d/95fcoe-uefi/module-setup.sh b/modules.d/95fcoe-uefi/module-setup.sh
new file mode 100755
index 0000000..9dc1e73
--- /dev/null
+++ b/modules.d/95fcoe-uefi/module-setup.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ is_fcoe() {
+ block_is_fcoe "$1" || return 1
+ }
+
+ [[ $hostonly ]] || [[ $mount_needs ]] && {
+ for_each_host_dev_and_slaves is_fcoe || return 255
+ [ -d /sys/firmware/efi ] || return 255
+ }
+
+ require_binaries dcbtool fipvlan lldpad ip readlink || return 1
+ return 0
+}
+
+# called by dracut
+depends() {
+ echo fcoe uefi-lib bash
+ return 0
+}
+
+# called by dracut
+install() {
+ inst_hook cmdline 20 "$moddir/parse-uefifcoe.sh"
+}
diff --git a/modules.d/95fcoe-uefi/parse-uefifcoe.sh b/modules.d/95fcoe-uefi/parse-uefifcoe.sh
new file mode 100755
index 0000000..e120dec
--- /dev/null
+++ b/modules.d/95fcoe-uefi/parse-uefifcoe.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+command -v getarg > /dev/null || . /lib/dracut-lib.sh
+command -v get_fcoe_boot_mac > /dev/null || . /lib/uefi-lib.sh
+command -v set_ifname > /dev/null || . /lib/net-lib.sh
+
+print_fcoe_uefi_conf() {
+ local mac dev vlan
+ mac=$(get_fcoe_boot_mac "$1")
+ [ -z "$mac" ] && return 1
+ dev=$(set_ifname fcoe "$mac")
+ vlan=$(get_fcoe_boot_vlan "$1")
+ if [ "$vlan" -ne "0" ]; then
+ case "$vlan" in
+ [0-9]*)
+ printf "%s\n" "vlan=$dev.$vlan:$dev"
+ dev="$dev.$vlan"
+ ;;
+ *)
+ printf "%s\n" "vlan=$vlan:$dev"
+ dev="$vlan"
+ ;;
+ esac
+ fi
+ # fcoe=eth0:nodcb
+ printf "fcoe=%s\n" "$dev:nodcb"
+ return 0
+}
+
+for i in /sys/firmware/efi/efivars/FcoeBootDevice-*; do
+ [ -e "$i" ] || continue
+ print_fcoe_uefi_conf "$i" > /etc/cmdline.d/40-fcoe-uefi.conf && break
+done
diff --git a/modules.d/95fcoe/cleanup-fcoe.sh b/modules.d/95fcoe/cleanup-fcoe.sh
new file mode 100755
index 0000000..210fb94
--- /dev/null
+++ b/modules.d/95fcoe/cleanup-fcoe.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+
+if [ -e /var/run/lldpad.pid ]; then
+ lldpad -k
+ # with systemd version 230, this is not necessary anymore
+ # systemd commit cacf980ed44a28e276a6cc7f8fc41f991e2ab354
+ if [ -z "$DRACUT_SYSTEMD" ]; then
+ # shellcheck disable=SC2174
+ mkdir -m 0755 -p /run/initramfs/state/dev/shm
+ cp /dev/shm/lldpad.state /run/initramfs/state/dev/shm/ > /dev/null 2>&1
+ echo "files /dev/shm/lldpad.state" >> /run/initramfs/rwtab
+ fi
+fi
diff --git a/modules.d/95fcoe/fcoe-edd.sh b/modules.d/95fcoe/fcoe-edd.sh
new file mode 100755
index 0000000..17f8a7c
--- /dev/null
+++ b/modules.d/95fcoe/fcoe-edd.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+
+dcb="$1"
+
+_modprobe_r_edd="0"
+
+check_edd() {
+ local cnt=0
+
+ [ -d /sys/firmware/edd ] && return 0
+
+ _modprobe_r_edd="1"
+ modprobe edd || return $?
+
+ while [ $cnt -lt 600 ]; do
+ [ -d /sys/firmware/edd ] && return 0
+ cnt=$((cnt + 1))
+ sleep 0.1
+ done
+ return 1
+}
+
+check_edd || exit 1
+
+for disk in /sys/firmware/edd/int13_*; do
+ [ -d "$disk" ] || continue
+ if [ -e "${disk}/pci_dev/driver" ]; then
+ driver=$(readlink "${disk}/pci_dev/driver")
+ driver=${driver##*/}
+ fi
+ # i40e uses dev_port 1 for a virtual fcoe function
+ if [ "${driver}" = "i40e" ]; then
+ dev_port=1
+ fi
+ for nic in "${disk}"/pci_dev/net/*; do
+ [ -d "$nic" ] || continue
+ if [ -n "${dev_port}" -a -e "${nic}/dev_port" ]; then
+ if [ "$(cat "${nic}"/dev_port)" -ne "${dev_port}" ]; then
+ continue
+ fi
+ fi
+ if [ -e "${nic}"/address ]; then
+ fcoe_interface=${nic##*/}
+ if ! [ -e "/tmp/.fcoe-$fcoe_interface" ]; then
+ /sbin/fcoe-up "$fcoe_interface" "$dcb"
+ : > "/tmp/.fcoe-$fcoe_interface"
+ fi
+ fi
+ done
+done
+
+[ "$_modprobe_r_edd" = "1" ] && modprobe -r edd
+
+unset _modprobe_r_edd
diff --git a/modules.d/95fcoe/fcoe-up.sh b/modules.d/95fcoe/fcoe-up.sh
new file mode 100755
index 0000000..0828f03
--- /dev/null
+++ b/modules.d/95fcoe/fcoe-up.sh
@@ -0,0 +1,106 @@
+#!/bin/sh
+#
+# We get called like this:
+# fcoe-up <network-device> <dcb|nodcb> <fabric|vn2vn>
+#
+# Note currently only nodcb is supported, the dcb option is reserved for
+# future use.
+
+PATH=/usr/sbin:/usr/bin:/sbin:/bin
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+type ip_to_var > /dev/null 2>&1 || . /lib/net-lib.sh
+
+# Huh? Missing arguments ??
+[ -z "$1" -o -z "$2" ] && exit 1
+
+netif=$1
+dcb=$2
+mode=$3
+vlan="yes"
+
+read -r iflink < /sys/class/net/"$netif"/iflink
+read -r ifindex < /sys/class/net/"$netif"/ifindex
+if [ "$iflink" != "$ifindex" ]; then
+ # Skip VLAN devices
+ exit 0
+fi
+
+ip link set dev "$netif" up
+linkup "$netif"
+
+# Some fcoemon implementations expect --syslog=true
+syslogopt="--syslog"
+if fcoemon -h | grep syslog | grep -q yes; then
+ syslogopt="$syslogopt=yes"
+fi
+
+netdriver=$(readlink -f /sys/class/net/"$netif"/device/driver)
+netdriver=${netdriver##*/}
+
+write_fcoemon_cfg() {
+ [ -f /etc/fcoe/cfg-"$netif" ] && return
+ echo FCOE_ENABLE=\"yes\" > /etc/fcoe/cfg-"$netif"
+ if [ "$dcb" = "dcb" ]; then
+ echo DCB_REQUIRED=\"yes\" >> /etc/fcoe/cfg-"$netif"
+ else
+ echo DCB_REQUIRED=\"no\" >> /etc/fcoe/cfg-"$netif"
+ fi
+ if [ "$vlan" = "yes" ]; then
+ echo AUTO_VLAN=\"yes\" >> /etc/fcoe/cfg-"$netif"
+ else
+ echo AUTO_VLAN=\"no\" >> /etc/fcoe/cfg-"$netif"
+ fi
+ if [ "$mode" = "vn2vn" ]; then
+ echo MODE=\"vn2vn\" >> /etc/fcoe/cfg-"$netif"
+ else
+ echo MODE=\"fabric\" >> /etc/fcoe/cfg-"$netif"
+ fi
+}
+
+if [ "$netdriver" = "bnx2x" ]; then
+ # If driver is bnx2x, do not use /sys/module/fcoe/parameters/create but fipvlan
+ modprobe 8021q
+ udevadm settle --timeout=30
+ # Sleep for 13 s to allow dcb negotiation
+ sleep 13
+ fipvlan "$netif" -c -s
+ need_shutdown
+ exit
+fi
+if [ "$dcb" = "dcb" ]; then
+ # wait for lldpad to be ready
+ i=0
+ while [ $i -lt 60 ]; do
+ lldptool -p && break
+ info "Waiting for lldpad to be ready"
+ sleep 1
+ i=$((i + 1))
+ done
+
+ while [ $i -lt 60 ]; do
+ dcbtool sc "$netif" dcb on && break
+ info "Retrying to turn dcb on"
+ sleep 1
+ i=$((i + 1))
+ done
+
+ while [ $i -lt 60 ]; do
+ dcbtool sc "$netif" pfc e:1 a:1 w:1 && break
+ info "Retrying to turn dcb on"
+ sleep 1
+ i=$((i + 1))
+ done
+
+ while [ $i -lt 60 ]; do
+ dcbtool sc "$netif" app:fcoe e:1 a:1 w:1 && break
+ info "Retrying to turn fcoe on"
+ sleep 1
+ i=$((i + 1))
+ done
+
+ sleep 1
+fi
+write_fcoemon_cfg
+fcoemon $syslogopt
+
+need_shutdown
diff --git a/modules.d/95fcoe/lldpad.sh b/modules.d/95fcoe/lldpad.sh
new file mode 100755
index 0000000..f992ae2
--- /dev/null
+++ b/modules.d/95fcoe/lldpad.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+if ! getargbool 1 rd.fcoe -d -n rd.nofcoe; then
+ info "rd.fcoe=0: skipping lldpad activation"
+ return 0
+fi
+
+# Note lldpad will stay running after switchroot, the system initscripts
+# are to kill it and start a new lldpad to take over. Data is transferred
+# between the 2 using a shm segment
+lldpad -d
+# wait for lldpad to be ready
+i=0
+while [ $i -lt 60 ]; do
+ lldptool -p && break
+ info "Waiting for lldpad to be ready"
+ sleep 1
+ i=$((i + 1))
+done
diff --git a/modules.d/95fcoe/module-setup.sh b/modules.d/95fcoe/module-setup.sh
new file mode 100755
index 0000000..3de85c2
--- /dev/null
+++ b/modules.d/95fcoe/module-setup.sh
@@ -0,0 +1,122 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ is_fcoe() {
+ block_is_fcoe "$1" || return 1
+ }
+
+ [[ $hostonly ]] || [[ $mount_needs ]] && {
+ for_each_host_dev_and_slaves is_fcoe || return 255
+ }
+
+ require_binaries dcbtool fipvlan lldpad ip readlink fcoemon fcoeadm tr || return 1
+ return 0
+}
+
+# called by dracut
+depends() {
+ echo network rootfs-block
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ instmods fcoe libfcoe 8021q edd bnx2fc
+}
+
+get_vlan_parent() {
+ local link=$1
+
+ [ -d "$link" ] || return
+ read -r iflink < "$link"/iflink
+ for if in /sys/class/net/*; do
+ read -r idx < "$if"/ifindex
+ if [ "$idx" -eq "$iflink" ]; then
+ echo "${if##*/}"
+ fi
+ done
+}
+
+# called by dracut
+cmdline() {
+ {
+ for c in /sys/bus/fcoe/devices/ctlr_*; do
+ [ -L "$c" ] || continue
+ read -r enabled < "$c"/enabled
+ read -r mode < "$c"/mode
+ [ "$enabled" -eq 0 ] && continue
+ if [ "$mode" = "VN2VN" ]; then
+ mode="vn2vn"
+ else
+ mode="fabric"
+ fi
+ d=$(
+ cd -P "$c" || exit
+ echo "$PWD"
+ )
+ i=${d%/*}
+ ifname=${i##*/}
+ read -r mac < "${i}"/address
+ s=$(dcbtool gc "${i##*/}" dcb 2> /dev/null | sed -n 's/^DCB State:\t*\(.*\)/\1/p')
+ if [ -z "$s" ]; then
+ p=$(get_vlan_parent "${i}")
+ if [ "$p" ]; then
+ s=$(dcbtool gc "${p}" dcb 2> /dev/null | sed -n 's/^DCB State:\t*\(.*\)/\1/p')
+ ifname=${p##*/}
+ fi
+ fi
+ if [ "$s" = "on" ]; then
+ dcb="dcb"
+ else
+ dcb="nodcb"
+ fi
+
+ # Some Combined Network Adapters(CNAs) implement DCB in firmware.
+ # Do not run software-based DCB or LLDP on CNAs that implement DCB.
+ # If the network interface provides hardware DCB/DCBX capabilities,
+ # DCB_REQUIRED in "/etc/fcoe/cfg-xxx" is expected to set to "no".
+ #
+ # Force "nodcb" if there's any DCB_REQUIRED="no"(child or vlan parent).
+ if grep -q '^[[:blank:]]*DCB_REQUIRED="no"' /etc/fcoe/cfg-"${i##*/}" &> /dev/null; then
+ dcb="nodcb"
+ fi
+
+ if [ "$p" ]; then
+ if grep -q '^[[:blank:]]*DCB_REQUIRED="no"' /etc/fcoe/cfg-"${p}" &> /dev/null; then
+ dcb="nodcb"
+ fi
+ fi
+
+ echo "ifname=${ifname}:${mac}"
+ echo "fcoe=${ifname}:${dcb}:${mode}"
+ done
+ } | sort | uniq
+}
+
+# called by dracut
+install() {
+ inst_multiple ip dcbtool fipvlan lldpad readlink lldptool fcoemon fcoeadm tr
+ if [[ -e $dracutsysrootdir/etc/hba.conf ]]; then
+ inst_libdir_file 'libhbalinux.so*'
+ inst_simple "/etc/hba.conf"
+ fi
+
+ mkdir -m 0755 -p "$initdir/var/lib/lldpad"
+ mkdir -m 0755 -p "$initdir/etc/fcoe"
+
+ if [[ $hostonly_cmdline == "yes" ]]; then
+ local _fcoeconf
+ _fcoeconf=$(cmdline)
+ [[ $_fcoeconf ]] && printf "%s\n" "$_fcoeconf" >> "${initdir}/etc/cmdline.d/95fcoe.conf"
+ fi
+ inst_multiple "/etc/fcoe/cfg-*"
+
+ inst "$moddir/fcoe-up.sh" "/sbin/fcoe-up"
+ inst "$moddir/fcoe-edd.sh" "/sbin/fcoe-edd"
+ inst_hook pre-trigger 03 "$moddir/lldpad.sh"
+ inst_hook cmdline 99 "$moddir/parse-fcoe.sh"
+ inst_hook cleanup 90 "$moddir/cleanup-fcoe.sh"
+ inst_hook shutdown 40 "$moddir/stop-fcoe.sh"
+ dracut_need_initqueue
+}
diff --git a/modules.d/95fcoe/parse-fcoe.sh b/modules.d/95fcoe/parse-fcoe.sh
new file mode 100755
index 0000000..bde6b62
--- /dev/null
+++ b/modules.d/95fcoe/parse-fcoe.sh
@@ -0,0 +1,106 @@
+#!/bin/sh
+#
+# Supported formats:
+# fcoe=<networkdevice>:<dcb|nodcb>:<fabric|vn2vn>
+# fcoe=<macaddress>:<dcb|nodcb>:<fabric|vn2vn>
+#
+# Note currently only nodcb is supported, the dcb option is reserved for
+# future use.
+#
+# Note letters in the macaddress must be lowercase!
+#
+# Examples:
+# fcoe=eth0:nodcb:vn2vn
+# fcoe=4a:3f:4c:04:f8:d7:nodcb:fabric
+
+if [ -z "$fcoe" ] && ! getarg fcoe=; then
+ # If it's not set we don't continue
+ return 0
+fi
+
+if ! getargbool 1 rd.fcoe -d -n rd.nofcoe; then
+ info "rd.fcoe=0: skipping fcoe"
+ return 0
+fi
+
+if ! [ -e /sys/bus/fcoe/ctlr_create ] && ! modprobe -b -a fcoe && ! modprobe -b -a libfcoe; then
+ die "FCoE requested but kernel/initrd does not support FCoE"
+fi
+
+initqueue --onetime modprobe -b -q bnx2fc
+
+parse_fcoe_opts() {
+ local fcoe_interface
+ local fcoe_dcb
+ local fcoe_mode
+ local fcoe_mac
+ local OLDIFS="$IFS"
+ local IFS=:
+ # shellcheck disable=SC2086
+ # shellcheck disable=SC2048
+ set -- $*
+ IFS="$OLDIFS"
+
+ case $# in
+ 2)
+ fcoe_interface=$1
+ fcoe_dcb=$2
+ fcoe_mode="fabric"
+ unset fcoe_mac
+ ;;
+ 3)
+ fcoe_interface=$1
+ fcoe_dcb=$2
+ fcoe_mode=$3
+ unset fcoe_mac
+ ;;
+ 7)
+ fcoe_mac=$(echo "$1:$2:$3:$4:$5:$6" | tr "[:upper:]" "[:lower:]")
+ fcoe_dcb=$7
+ fcoe_mode="fabric"
+ unset fcoe_interface
+ ;;
+ 8)
+ fcoe_mac=$(echo "$1:$2:$3:$4:$5:$6" | tr "[:upper:]" "[:lower:]")
+ fcoe_dcb=$7
+ fcoe_mode=$8
+ unset fcoe_interface
+ ;;
+ *)
+ warn "Invalid arguments for fcoe=$fcoe"
+ return 1
+ ;;
+ esac
+
+ if [ "$fcoe_dcb" != "nodcb" -a "$fcoe_dcb" != "dcb" ]; then
+ warn "Invalid FCoE DCB option: $fcoe_dcb"
+ fi
+
+ if [ "$fcoe_interface" = "edd" ]; then
+ /sbin/initqueue --settled --unique /sbin/fcoe-edd "$fcoe_dcb"
+ return 0
+ fi
+
+ if [ -z "$fcoe_interface" -a -z "$fcoe_mac" ]; then
+ warn "fcoe: Neither interface nor MAC specified for fcoe=$fcoe"
+ return 1
+ fi
+
+ {
+ if [ -n "$fcoe_mac" ]; then
+ # shellcheck disable=SC2016
+ printf 'ACTION=="add", SUBSYSTEM=="net", ATTR{address}=="%s", RUN+="/sbin/initqueue --onetime --unique --name fcoe-up-$name /sbin/fcoe-up $name %s %s"\n' "$fcoe_mac" "$fcoe_dcb" "$fcoe_mode"
+ # shellcheck disable=SC2016
+ printf 'ACTION=="add", SUBSYSTEM=="net", ATTR{address}=="%s", RUN+="/sbin/initqueue --onetime --timeout --unique --name fcoe-timeout-$name /sbin/fcoe-up $name %s %s"\n' "$fcoe_mac" "$fcoe_dcb" "$fcoe_mode"
+ else
+ # shellcheck disable=SC2016
+ printf 'ACTION=="add", SUBSYSTEM=="net", NAME=="%s", RUN+="/sbin/initqueue --onetime --unique --name fcoe-up-$name /sbin/fcoe-up $name %s %s"\n' "$fcoe_interface" "$fcoe_dcb" "$fcoe_mode"
+ # shellcheck disable=SC2016
+ printf 'ACTION=="add", SUBSYSTEM=="net", NAME=="%s", RUN+="/sbin/initqueue --onetime --timeout --unique --name fcoe-timeout-$name /sbin/fcoe-up $name %s %s"\n' "$fcoe_interface" "$fcoe_dcb" "$fcoe_mode"
+ fi
+ } >> /etc/udev/rules.d/92-fcoe.rules
+}
+
+for fcoe in $fcoe $(getargs fcoe=); do
+ parse_fcoe_opts "$fcoe"
+done
diff --git a/modules.d/95fcoe/stop-fcoe.sh b/modules.d/95fcoe/stop-fcoe.sh
new file mode 100755
index 0000000..a89cbbc
--- /dev/null
+++ b/modules.d/95fcoe/stop-fcoe.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+for f in /sys/bus/fcoe/devices/ctlr_*; do
+ [ -e "$f" ] || continue
+ echo 0 > "$f"/enabled
+done
diff --git a/modules.d/95fstab-sys/module-setup.sh b/modules.d/95fstab-sys/module-setup.sh
new file mode 100755
index 0000000..e58f0d8
--- /dev/null
+++ b/modules.d/95fstab-sys/module-setup.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ [[ -f $dracutsysrootdir/etc/fstab.sys ]] || [[ -n $add_fstab || -n $fstab_lines ]]
+}
+
+# called by dracut
+depends() {
+ echo fs-lib
+}
+
+# called by dracut
+install() {
+ [[ -f $dracutsysrootdir/etc/fstab.sys ]] && inst_simple /etc/fstab.sys
+ inst_hook pre-pivot 00 "$moddir/mount-sys.sh"
+}
diff --git a/modules.d/95fstab-sys/mount-sys.sh b/modules.d/95fstab-sys/mount-sys.sh
new file mode 100755
index 0000000..bb4bcdb
--- /dev/null
+++ b/modules.d/95fstab-sys/mount-sys.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+type det_fs > /dev/null 2>&1 || . /lib/fs-lib.sh
+
+fstab_mount() {
+ local _dev _mp _fs _opts _pass
+ test -e "$1" || return 1
+ info "Mounting from $1"
+ while read -r _dev _mp _fs _opts _ _pass _ || [ -n "$_dev" ]; do
+ [ -z "${_dev%%#*}" ] && continue # Skip comment lines
+ ismounted "$_mp" && continue # Skip mounted filesystem
+ if [ "$_pass" -gt 0 ] && ! strstr "$_opts" _netdev; then
+ fsck_single "$_dev" "$_fs" "$_opts"
+ fi
+ _fs=$(det_fs "$_dev" "$_fs")
+ info "Mounting $_dev"
+ if [ -d "$NEWROOT/$_mp" ]; then
+ mount -v -t "$_fs" -o "$_opts" "$_dev" "$NEWROOT/$_mp" 2>&1 | vinfo
+ else
+ [ -d "$_mp" ] || mkdir -p "$_mp"
+ mount -v -t "$_fs" -o "$_opts" "$_dev" "$_mp" 2>&1 | vinfo
+ fi
+ done < "$1"
+ return 0
+}
+
+# systemd will mount and run fsck from /etc/fstab and we don't want to
+# run into a race condition.
+if [ -z "$DRACUT_SYSTEMD" ]; then
+ [ -f /etc/fstab ] && fstab_mount /etc/fstab
+fi
+
+# prefer $NEWROOT/etc/fstab.sys over local /etc/fstab.sys
+if [ -f "$NEWROOT"/etc/fstab.sys ]; then
+ fstab_mount "$NEWROOT"/etc/fstab.sys
+elif [ -f /etc/fstab.sys ]; then
+ fstab_mount /etc/fstab.sys
+fi
diff --git a/modules.d/95iscsi/cleanup-iscsi.sh b/modules.d/95iscsi/cleanup-iscsi.sh
new file mode 100755
index 0000000..8338503
--- /dev/null
+++ b/modules.d/95iscsi/cleanup-iscsi.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+if [ -z "${DRACUT_SYSTEMD}" ] && { [ -e /sys/module/bnx2i ] || [ -e /sys/module/qedi ]; }; then
+ killproc iscsiuio
+fi
diff --git a/modules.d/95iscsi/iscsiroot.sh b/modules.d/95iscsi/iscsiroot.sh
new file mode 100755
index 0000000..b6af7f4
--- /dev/null
+++ b/modules.d/95iscsi/iscsiroot.sh
@@ -0,0 +1,322 @@
+#!/bin/sh
+#
+# This implementation is incomplete: Discovery mode is not implemented and
+# the argument handling doesn't follow currently agreed formats. This is mainly
+# because rfc4173 does not say anything about iscsi_initiator but open-iscsi's
+# iscsistart needs this.
+#
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+type parse_iscsi_root > /dev/null 2>&1 || . /lib/net-lib.sh
+type write_fs_tab > /dev/null 2>&1 || . /lib/fs-lib.sh
+
+PATH=/usr/sbin:/usr/bin:/sbin:/bin
+
+# Huh? Empty $1?
+[ -z "$1" ] && exit 1
+
+# Huh? Empty $2?
+[ -z "$2" ] && exit 1
+
+# Huh? Empty $3? This isn't really necessary, since NEWROOT isn't
+# used here. But let's be consistent
+[ -z "$3" ] && exit 1
+
+# root is in the form root=iscsi:[<servername>]:[<protocol>]:[<port>]:[<LUN>]:<targetname>
+netif="$1"
+iroot="$2"
+
+# If it's not iscsi we don't continue
+[ "${iroot%%:*}" = "iscsi" ] || exit 1
+
+iroot=${iroot#iscsi}
+iroot=${iroot#:}
+
+# XXX modprobe crc32c should go in the cmdline parser, but I haven't yet
+# figured out a way how to check whether this is built-in or not
+modprobe crc32c 2> /dev/null
+
+# start iscsiuio if needed
+if [ -z "${DRACUT_SYSTEMD}" ] \
+ && { [ -e /sys/module/bnx2i ] || [ -e /sys/module/qedi ]; } \
+ && ! [ -e /tmp/iscsiuio-started ]; then
+ iscsiuio
+ : > /tmp/iscsiuio-started
+fi
+
+handle_firmware() {
+ local ifaces retry _res
+
+ # Depending on the 'ql4xdisablesysfsboot' qla4xxx
+ # will be autostarting sessions without presenting
+ # them via the firmware interface.
+ # In these cases 'iscsiadm -m fw' will fail, but
+ # the iSCSI sessions will still be present.
+ if ! iscsiadm -m fw; then
+ warn "iscsiadm: Could not get list of targets from firmware."
+ else
+ ifaces=$(
+ set -- /sys/firmware/ibft/ethernet*
+ echo $#
+ )
+ read -r retry < /tmp/session-retry
+
+ if [ "$retry" -lt "$ifaces" ]; then
+ retry=$((retry + 1))
+ echo $retry > /tmp/session-retry
+ return 1
+ else
+ rm /tmp/session-retry
+ fi
+
+ # check to see if we have the new iscsiadm command,
+ # that supports the "no-wait" (-W) flag. If so, use it.
+ iscsiadm -m fw -l -W 2> /dev/null
+ _res=$?
+ if [ $_res -eq 7 ]; then
+ # ISCSI_ERR_INVALID (7) => "-W" not supported
+ info "iscsiadm does not support no-wait firmware logins"
+ iscsiadm -m fw -l
+ _res=$?
+ fi
+ if [ $_res -ne 0 ]; then
+ warn "iscsiadm: Log-in to iscsi target failed"
+ else
+ need_shutdown
+ fi
+ fi
+ [ -d /sys/class/iscsi_session ] || return 1
+ echo 'started' > "/tmp/iscsistarted-iscsi:"
+ echo 'started' > "/tmp/iscsistarted-firmware"
+
+ return 0
+}
+
+handle_netroot() {
+ local iscsi_initiator iscsi_target_name iscsi_target_ip iscsi_target_port
+ local iscsi_target_group iscsirw iscsi_lun
+ local iscsi_username iscsi_password
+ local iscsi_in_username iscsi_in_password
+ local iscsi_iface_name iscsi_netdev_name
+ local iscsi_param param
+ local p found
+ local login_retry_max_seen=
+
+ # override conf settings by command line options
+ arg=$(getarg rd.iscsi.initiator -d iscsi_initiator=)
+ [ -n "$arg" ] && iscsi_initiator=$arg
+ arg=$(getarg rd.iscsi.target.group -d iscsi_target_group=)
+ [ -n "$arg" ] && iscsi_target_group=$arg
+ arg=$(getarg rd.iscsi.username -d iscsi_username=)
+ [ -n "$arg" ] && iscsi_username=$arg
+ arg=$(getarg rd.iscsi.password -d iscsi_password)
+ [ -n "$arg" ] && iscsi_password=$arg
+ arg=$(getarg rd.iscsi.in.username -d iscsi_in_username=)
+ [ -n "$arg" ] && iscsi_in_username=$arg
+ arg=$(getarg rd.iscsi.in.password -d iscsi_in_password=)
+ [ -n "$arg" ] && iscsi_in_password=$arg
+ for p in $(getargs rd.iscsi.param -d iscsi_param); do
+ [ "${p%=*}" = node.session.initial_login_retry_max ] \
+ && login_retry_max_seen=yes
+ iscsi_param="$iscsi_param $p"
+ done
+
+ # this sets iscsi_target_name and possibly overwrites most
+ # parameters read from the command line above
+ parse_iscsi_root "$1" || return 1
+
+ # Bail out early, if there is no route to the destination
+ if is_ip "$iscsi_target_ip" && [ "$netif" != "timeout" ] && ! all_ifaces_setup && getargbool 1 rd.iscsi.testroute; then
+ ip route get "$iscsi_target_ip" > /dev/null 2>&1 || return 0
+ fi
+
+ #limit iscsistart login retries
+ if [ "$login_retry_max_seen" != yes ]; then
+ retries=$(getargnum 3 0 10000 rd.iscsi.login_retry_max)
+ if [ "$retries" -gt 0 ]; then
+ iscsi_param="${iscsi_param% } node.session.initial_login_retry_max=$retries"
+ fi
+ fi
+
+ # XXX is this needed?
+ getarg ro && iscsirw=ro
+ getarg rw && iscsirw=rw
+ fsopts=${fsopts:+$fsopts,}${iscsirw}
+
+ if [ -z "$iscsi_initiator" ] && [ -f /sys/firmware/ibft/initiator/initiator-name ] && ! [ -f /tmp/iscsi_set_initiator ]; then
+ iscsi_initiator=$(while read -r line || [ -n "$line" ]; do echo "$line"; done < /sys/firmware/ibft/initiator/initiator-name)
+ echo "InitiatorName=$iscsi_initiator" > /run/initiatorname.iscsi
+ rm -f /etc/iscsi/initiatorname.iscsi
+ mkdir -p /etc/iscsi
+ ln -fs /run/initiatorname.iscsi /etc/iscsi/initiatorname.iscsi
+ : > /tmp/iscsi_set_initiator
+ if [ -n "$DRACUT_SYSTEMD" ]; then
+ systemctl try-restart iscsid
+ # FIXME: iscsid is not yet ready, when the service is :-/
+ sleep 1
+ fi
+ fi
+
+ if [ -z "$iscsi_initiator" ]; then
+ [ -f /run/initiatorname.iscsi ] && . /run/initiatorname.iscsi
+ [ -f /etc/initiatorname.iscsi ] && . /etc/initiatorname.iscsi
+ [ -f /etc/iscsi/initiatorname.iscsi ] && . /etc/iscsi/initiatorname.iscsi
+ iscsi_initiator=$InitiatorName
+ fi
+
+ if [ -z "$iscsi_initiator" ]; then
+ iscsi_initiator=$(iscsi-iname)
+ echo "InitiatorName=$iscsi_initiator" > /run/initiatorname.iscsi
+ rm -f /etc/iscsi/initiatorname.iscsi
+ mkdir -p /etc/iscsi
+ ln -fs /run/initiatorname.iscsi /etc/iscsi/initiatorname.iscsi
+ : > /tmp/iscsi_set_initiator
+ if [ -n "$DRACUT_SYSTEMD" ]; then
+ systemctl try-restart iscsid
+ # FIXME: iscsid is not yet ready, when the service is :-/
+ sleep 1
+ fi
+ fi
+
+ if [ -z "$iscsi_target_port" ]; then
+ iscsi_target_port=3260
+ fi
+
+ if [ -z "$iscsi_target_group" ]; then
+ iscsi_target_group=1
+ fi
+
+ if [ -z "$iscsi_lun" ]; then
+ iscsi_lun=0
+ fi
+
+ echo "InitiatorName=$iscsi_initiator" > /run/initiatorname.iscsi
+ ln -fs /run/initiatorname.iscsi /dev/.initiatorname.iscsi
+ if ! [ -e /etc/iscsi/initiatorname.iscsi ]; then
+ mkdir -p /etc/iscsi
+ ln -fs /run/initiatorname.iscsi /etc/iscsi/initiatorname.iscsi
+ if [ -n "$DRACUT_SYSTEMD" ]; then
+ systemctl try-restart iscsid
+ # FIXME: iscsid is not yet ready, when the service is :-/
+ sleep 1
+ fi
+ fi
+
+ if [ -z "$DRACUT_SYSTEMD" ]; then
+ iscsid
+ sleep 2
+ fi
+
+ # FIXME $iscsi_protocol??
+
+ if [ "$root" = "dhcp" ] || [ "$netroot" = "dhcp" ]; then
+ # if root is not specified try to mount the whole iSCSI LUN
+ printf 'SYMLINK=="disk/by-path/*-iscsi-*-%s", SYMLINK+="root"\n' "$iscsi_lun" >> /etc/udev/rules.d/99-iscsi-root.rules
+ udevadm control --reload
+ write_fs_tab /dev/root
+ wait_for_dev -n /dev/root
+
+ # install mount script
+ [ -z "$DRACUT_SYSTEMD" ] \
+ && echo "iscsi_lun=$iscsi_lun . /bin/mount-lun.sh " > "$hookdir"/mount/01-$$-iscsi.sh
+ fi
+
+ if strglobin "$iscsi_target_ip" '*:*:*' && ! strglobin "$iscsi_target_ip" '['; then
+ iscsi_target_ip="[$iscsi_target_ip]"
+ fi
+ targets=$(iscsiadm -m discovery -t st -p "$iscsi_target_ip":${iscsi_target_port:+$iscsi_target_port} | {
+ while read -r _ target _ || [ -n "$target" ]; do
+ echo "$target"
+ done
+ })
+ [ -z "$targets" ] && warn "Target discovery to $iscsi_target_ip:${iscsi_target_port:+$iscsi_target_port} failed with status $?" && return 1
+
+ found=
+ for target in $targets; do
+ if [ "$target" = "$iscsi_target_name" ]; then
+ if [ -n "$iscsi_iface_name" ]; then
+ iscsiadm -m iface -I "$iscsi_iface_name" --op=new
+ EXTRA=" ${iscsi_netdev_name:+--name=iface.net_ifacename --value=$iscsi_netdev_name} "
+ EXTRA="$EXTRA ${iscsi_initiator:+--name=iface.initiatorname --value=$iscsi_initiator} "
+ fi
+ [ -n "$iscsi_param" ] && for param in $iscsi_param; do EXTRA="$EXTRA --name=${param%=*} --value=${param#*=}"; done
+
+ CMD="iscsiadm -m node -T $target \
+ ${iscsi_iface_name:+-I $iscsi_iface_name} \
+ -p $iscsi_target_ip${iscsi_target_port:+:$iscsi_target_port}"
+ __op="--op=update \
+ --name=node.startup --value=onboot \
+ ${iscsi_username:+ --name=node.session.auth.username --value=$iscsi_username} \
+ ${iscsi_password:+ --name=node.session.auth.password --value=$iscsi_password} \
+ ${iscsi_in_username:+--name=node.session.auth.username_in --value=$iscsi_in_username} \
+ ${iscsi_in_password:+--name=node.session.auth.password_in --value=$iscsi_in_password} \
+ $EXTRA"
+ # shellcheck disable=SC2086
+ $CMD $__op
+ if [ "$netif" != "timeout" ]; then
+ $CMD --login
+ fi
+ found=yes
+ break
+ fi
+ done
+
+ if [ "$netif" = "timeout" ]; then
+ iscsiadm -m node -L onboot || :
+ elif [ "$found" != yes ]; then
+ warn "iSCSI target \"$iscsi_target_name\" not found on portal $iscsi_target_ip:$iscsi_target_port"
+ return 1
+ fi
+ : > "$hookdir"/initqueue/work
+
+ netroot_enc=$(str_replace "$1" '/' '\2f')
+ echo 'started' > "/tmp/iscsistarted-iscsi:${netroot_enc}"
+ return 0
+}
+
+ret=0
+
+if [ "$netif" != "timeout" ] && getargbool 0 rd.iscsi.waitnet; then
+ all_ifaces_setup || exit 0
+fi
+
+if [ "$netif" = "timeout" ] && all_ifaces_setup; then
+ # s.th. went wrong and the timeout script hits
+ # restart
+ systemctl restart iscsid
+ # damn iscsid is not ready after unit says it's ready
+ sleep 2
+fi
+
+if getargbool 0 rd.iscsi.firmware -d -y iscsi_firmware; then
+ if [ "$netif" = "timeout" ] || [ "$netif" = "online" ] || [ "$netif" = "dummy" ]; then
+ [ -f /tmp/session-retry ] || echo 1 > /tmp/session-retry
+ handle_firmware
+ ret=$?
+ fi
+fi
+
+if ! [ "$netif" = "online" ]; then
+ # loop over all netroot parameter
+ if nroot=$(getarg netroot) && [ "$nroot" != "dhcp" ]; then
+ for nroot in $(getargs netroot); do
+ [ "${nroot%%:*}" = "iscsi" ] || continue
+ nroot="${nroot##iscsi:}"
+ if [ -n "$nroot" ]; then
+ handle_netroot "$nroot"
+ ret=$((ret + $?))
+ fi
+ done
+ else
+ if [ -n "$iroot" ]; then
+ handle_netroot "$iroot"
+ ret=$?
+ fi
+ fi
+fi
+
+need_shutdown
+
+# now we have a root filesystem somewhere in /dev/sd*
+# let the normal block handler handle root=
+exit $ret
diff --git a/modules.d/95iscsi/module-setup.sh b/modules.d/95iscsi/module-setup.sh
new file mode 100755
index 0000000..2bea2fc
--- /dev/null
+++ b/modules.d/95iscsi/module-setup.sh
@@ -0,0 +1,294 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ # If our prerequisites are not met, fail anyways.
+ require_binaries iscsi-iname iscsiadm iscsid || return 1
+ require_kernel_modules iscsi_tcp || return 1
+
+ # If hostonly was requested, fail the check if we are not actually
+ # booting from root.
+ [[ $hostonly ]] || [[ $mount_needs ]] && {
+ pushd . > /dev/null
+ for_each_host_dev_and_slaves block_is_iscsi
+ local _is_iscsi=$?
+ popd > /dev/null || exit
+ [[ $_is_iscsi == 0 ]] || return 255
+ }
+ return 0
+}
+
+get_ibft_mod() {
+ local ibft_mac=$1
+ local iface_mac iface_mod
+ # Return the iSCSI offload module for a given MAC address
+ for iface_desc in $(iscsiadm -m iface | cut -f 2 -d ' '); do
+ iface_mod=${iface_desc%%,*}
+ iface_mac=${iface_desc#*,}
+ iface_mac=${iface_mac%%,*}
+ if [ "$ibft_mac" = "$iface_mac" ]; then
+ echo "$iface_mod"
+ return 0
+ fi
+ done
+}
+
+install_ibft() {
+ # When iBFT / iscsi_boot is detected:
+ # - Use 'ip=ibft' to set up iBFT network interface
+ # Note: bnx2i is using a different MAC address of iSCSI offloading
+ # so the 'ip=ibft' parameter must not be set
+ # - specify firmware booting cmdline parameter
+
+ for d in /sys/firmware/*; do
+ if [ -d "${d}"/ethernet0 ]; then
+ read -r ibft_mac < "${d}"/ethernet0/mac
+ ibft_mod=$(get_ibft_mod "$ibft_mac")
+ fi
+ if [ -z "$ibft_mod" ] && [ -d "${d}"/ethernet1 ]; then
+ read -r ibft_mac < "${d}"/ethernet1/mac
+ ibft_mod=$(get_ibft_mod "$ibft_mac")
+ fi
+ if [ -d "${d}"/initiator ]; then
+ if [ "${d##*/}" = "ibft" ] && [ "$ibft_mod" != "bnx2i" ]; then
+ echo -n "rd.iscsi.ibft=1 "
+ fi
+ echo -n "rd.iscsi.firmware=1 "
+ fi
+ done
+}
+
+install_iscsiroot() {
+ local devpath=$1
+ local scsi_path iscsi_lun session c d conn host flash
+ local iscsi_session iscsi_address iscsi_port iscsi_targetname
+
+ scsi_path=${devpath%%/block*}
+ [ "$scsi_path" = "$devpath" ] && return 1
+ iscsi_lun=${scsi_path##*:}
+ [ "$iscsi_lun" = "$scsi_path" ] && return 1
+ session=${devpath%%/target*}
+ [ "$session" = "$devpath" ] && return 1
+ iscsi_session=${session##*/}
+ [ "$iscsi_session" = "$session" ] && return 1
+ host=${session%%/session*}
+ [ "$host" = "$session" ] && return 1
+ iscsi_host=${host##*/}
+
+ for flash in "${host}"/flashnode_sess-*; do
+ [ -f "$flash" ] || continue
+ [ ! -e "$flash/is_boot_target" ] && continue
+ read -r is_boot < "$flash"/is_boot_target
+ if [ "$is_boot" -eq 1 ]; then
+ # qla4xxx flashnode session; skip iBFT discovery
+ read -r iscsi_initiator < /sys/class/iscsi_host/"${iscsi_host}"/initiatorname
+ echo "rd.iscsi.initiator=${iscsi_initiator}"
+ return
+ fi
+ done
+
+ for d in "${session}"/*; do
+ case $d in
+ *connection*)
+ c=${d##*/}
+ conn=${d}/iscsi_connection/${c}
+ if [ -d "${conn}" ]; then
+ read -r iscsi_address < "${conn}"/persistent_address
+ read -r iscsi_port < "${conn}"/persistent_port
+ fi
+ ;;
+ *session)
+ if [ -d "${d}"/"${iscsi_session}" ]; then
+ read -r iscsi_initiator < "${d}"/"${iscsi_session}"/initiatorname
+ read -r iscsi_targetname < "${d}"/"${iscsi_session}"/targetname
+ fi
+ ;;
+ esac
+ done
+
+ [ -z "$iscsi_address" ] && return
+ ip_params_for_remote_addr "$iscsi_address"
+
+ if [ -n "$iscsi_address" -a -n "$iscsi_targetname" ]; then
+ if [ -n "$iscsi_port" -a "$iscsi_port" -eq 3260 ]; then
+ iscsi_port=
+ fi
+ if [ -n "$iscsi_lun" -a "$iscsi_lun" -eq 0 ]; then
+ iscsi_lun=
+ fi
+ # In IPv6 case rd.iscsi.initatior= must pass address in [] brackets
+ case "$iscsi_address" in
+ *:*)
+ iscsi_address="[$iscsi_address]"
+ ;;
+ esac
+ # Must be two separate lines, so that "sort | uniq" commands later
+ # can sort out rd.iscsi.initiator= duplicates
+ echo "rd.iscsi.initiator=${iscsi_initiator}"
+ echo "netroot=iscsi:${iscsi_address}::${iscsi_port}:${iscsi_lun}:${iscsi_targetname}"
+ echo "rd.neednet=1"
+ fi
+ return 0
+}
+
+install_softiscsi() {
+ [ -d /sys/firmware/ibft ] && return 0
+
+ is_softiscsi() {
+ local _dev=$1
+ local iscsi_dev
+
+ [[ -L "/sys/dev/block/$_dev" ]] || return
+ iscsi_dev=$(
+ cd -P /sys/dev/block/"$_dev" || exit
+ echo "$PWD"
+ )
+ install_iscsiroot "$iscsi_dev"
+ }
+
+ for_each_host_dev_and_slaves_all is_softiscsi || return 255
+ return 0
+}
+
+# called by dracut
+depends() {
+ echo network rootfs-block
+}
+
+# called by dracut
+installkernel() {
+ local _arch=${DRACUT_ARCH:-$(uname -m)}
+ local _funcs='iscsi_register_transport'
+
+ instmods bnx2i qla4xxx cxgb3i cxgb4i be2iscsi qedi
+ hostonly="" instmods iscsi_tcp iscsi_ibft crc32c iscsi_boot_sysfs 8021q
+
+ if [ "$_arch" = "s390" -o "$_arch" = "s390x" ]; then
+ _s390drivers="=drivers/s390/scsi"
+ fi
+
+ dracut_instmods -o -s ${_funcs} =drivers/scsi ${_s390drivers:+"$_s390drivers"}
+}
+
+# called by dracut
+cmdline() {
+ local _iscsiconf
+ _iscsiconf=$(install_ibft)
+ {
+ if [ "$_iscsiconf" ]; then
+ echo "${_iscsiconf}"
+ else
+ install_softiscsi
+ fi
+ } | sort | uniq
+}
+
+# called by dracut
+install() {
+ inst_multiple -o iscsiuio
+ inst_libdir_file 'libgcc_s.so*'
+ inst_multiple umount iscsi-iname iscsiadm iscsid
+ inst_binary sort
+
+ inst_multiple -o \
+ "$systemdsystemunitdir"/iscsid.socket \
+ "$systemdsystemunitdir"/iscsid.service \
+ "$systemdsystemunitdir"/iscsiuio.service \
+ "$systemdsystemunitdir"/iscsiuio.socket \
+ "$systemdsystemunitdir"/sockets.target.wants/iscsid.socket \
+ "$systemdsystemunitdir"/sockets.target.wants/iscsiuio.socket
+
+ if [[ $hostonly ]]; then
+ local -a _filenames
+
+ inst_dir /etc/iscsi
+ mapfile -t -d '' _filenames < <(find /etc/iscsi -type f -print0)
+ inst_multiple "${_filenames[@]}"
+ else
+ inst_simple /etc/iscsi/iscsid.conf
+ fi
+
+ # Detect iBFT and perform mandatory steps
+ if [[ $hostonly_cmdline == "yes" ]]; then
+ local _iscsiconf
+ _iscsiconf=$(cmdline)
+ [[ $_iscsiconf ]] && printf "%s\n" "$_iscsiconf" >> "${initdir}/etc/cmdline.d/95iscsi.conf"
+ fi
+
+ inst_hook cmdline 90 "$moddir/parse-iscsiroot.sh"
+ inst_hook cleanup 90 "$moddir/cleanup-iscsi.sh"
+ inst "$moddir/iscsiroot.sh" "/sbin/iscsiroot"
+
+ if ! dracut_module_included "systemd"; then
+ inst "$moddir/mount-lun.sh" "/bin/mount-lun.sh"
+ else
+ inst_multiple -o \
+ "$systemdsystemunitdir"/iscsi.service \
+ "$systemdsystemunitdir"/iscsi-init.service \
+ "$systemdsystemunitdir"/iscsid.service \
+ "$systemdsystemunitdir"/iscsid.socket \
+ "$systemdsystemunitdir"/iscsiuio.service \
+ "$systemdsystemunitdir"/iscsiuio.socket \
+ iscsiadm iscsid
+
+ for i in \
+ iscsid.socket \
+ iscsiuio.socket; do
+ $SYSTEMCTL -q --root "$initdir" enable "$i"
+ done
+
+ mkdir -p "${initdir}/$systemdsystemunitdir/iscsid.service.d"
+ {
+ echo "[Unit]"
+ echo "DefaultDependencies=no"
+ echo "Conflicts=shutdown.target"
+ echo "Before=shutdown.target"
+ } > "${initdir}/$systemdsystemunitdir/iscsid.service.d/dracut.conf"
+
+ mkdir -p "${initdir}/$systemdsystemunitdir/iscsid.socket.d"
+ {
+ echo "[Unit]"
+ echo "DefaultDependencies=no"
+ echo "Conflicts=shutdown.target"
+ echo "Before=shutdown.target sockets.target"
+ } > "${initdir}/$systemdsystemunitdir/iscsid.socket.d/dracut.conf"
+
+ mkdir -p "${initdir}/$systemdsystemunitdir/iscsiuio.service.d"
+ {
+ echo "[Unit]"
+ echo "DefaultDependencies=no"
+ echo "Conflicts=shutdown.target"
+ echo "Before=shutdown.target"
+ } > "${initdir}/$systemdsystemunitdir/iscsiuio.service.d/dracut.conf"
+
+ mkdir -p "${initdir}/$systemdsystemunitdir/iscsiuio.socket.d"
+ {
+ echo "[Unit]"
+ echo "DefaultDependencies=no"
+ echo "Conflicts=shutdown.target"
+ echo "Before=shutdown.target sockets.target"
+ } > "${initdir}/$systemdsystemunitdir/iscsiuio.socket.d/dracut.conf"
+
+ # Fedora 34 iscsid requires iscsi-shutdown.service
+ # which would terminate all iSCSI connections on switch root
+ cat > "${initdir}/$systemdsystemunitdir/iscsi-shutdown.service" << EOF
+[Unit]
+Description=Dummy iscsi-shutdown.service for the initrd
+Documentation=man:iscsid(8) man:iscsiadm(8)
+DefaultDependencies=no
+Conflicts=shutdown.target
+After=systemd-remount-fs.service network.target iscsid.service iscsiuio.service
+Before=remote-fs-pre.target
+
+[Service]
+Type=oneshot
+RemainAfterExit=false
+ExecStart=-/usr/bin/true
+EOF
+ fi
+ inst_dir /var/lib/iscsi
+ mkdir -p "${initdir}/var/lib/iscsi/nodes"
+ # Fedora 34 iscsid wants a non-empty /var/lib/iscsi/nodes directory
+ : > "${initdir}/var/lib/iscsi/nodes/.dracut"
+ dracut_need_initqueue
+}
diff --git a/modules.d/95iscsi/mount-lun.sh b/modules.d/95iscsi/mount-lun.sh
new file mode 100755
index 0000000..c186984
--- /dev/null
+++ b/modules.d/95iscsi/mount-lun.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+if [ -z "$iscsi_lun" ]; then
+ iscsi_lun=0
+fi
+NEWROOT=${NEWROOT:-/sysroot}
+
+for disk in /dev/disk/by-path/*-iscsi-*-"$iscsi_lun"; do
+ if mount -t "${fstype:-auto}" -o "$rflags" "$disk" "$NEWROOT"; then
+ if [ ! -d "$NEWROOT"/proc ]; then
+ umount "$disk"
+ continue
+ fi
+ break
+ fi
+done
diff --git a/modules.d/95iscsi/parse-iscsiroot.sh b/modules.d/95iscsi/parse-iscsiroot.sh
new file mode 100755
index 0000000..7574711
--- /dev/null
+++ b/modules.d/95iscsi/parse-iscsiroot.sh
@@ -0,0 +1,156 @@
+#!/bin/sh
+#
+# Preferred format:
+# root=iscsi:[<servername>]:[<protocol>]:[<port>]:[<LUN>]:<targetname>
+# [root=*] netroot=iscsi:[<servername>]:[<protocol>]:[<port>]:[<LUN>]:<targetname>
+#
+# Legacy formats:
+# [net]root=[iscsi] iscsiroot=[<servername>]:[<protocol>]:[<port>]:[<LUN>]:<targetname>
+# [net]root=[iscsi] iscsi_firmware
+#
+# root= takes precedence over netroot= if root=iscsi[...]
+#
+
+# This script is sourced, so root should be set. But let's be paranoid
+[ -z "$root" ] && root=$(getarg root=)
+if [ -z "$netroot" ]; then
+ for nroot in $(getargs netroot=); do
+ [ "${nroot%%:*}" = "iscsi" ] && break
+ done
+ if [ "${nroot%%:*}" = "iscsi" ]; then
+ netroot="$nroot"
+ else
+ for nroot in $(getargs netroot=); do
+ [ "${nroot%%:*}" = "dhcp" ] && break
+ done
+ netroot="$nroot"
+ fi
+fi
+[ -z "$iscsiroot" ] && iscsiroot=$(getarg iscsiroot=)
+[ -z "$iscsi_firmware" ] && getargbool 0 rd.iscsi.firmware -y iscsi_firmware && iscsi_firmware="1"
+
+[ -n "$iscsiroot" ] && [ -n "$iscsi_firmware" ] && die "Mixing iscsiroot and iscsi_firmware is dangerous"
+
+type write_fs_tab > /dev/null 2>&1 || . /lib/fs-lib.sh
+
+# Root takes precedence over netroot
+if [ "${root%%:*}" = "iscsi" ]; then
+ if [ -n "$netroot" ]; then
+ echo "Warning: root takes precedence over netroot. Ignoring netroot"
+ fi
+ netroot=$root
+ # if root is not specified try to mount the whole iSCSI LUN
+ printf 'ENV{DEVTYPE}!="partition", SYMLINK=="disk/by-path/*-iscsi-*-*", SYMLINK+="root"\n' >> /etc/udev/rules.d/99-iscsi-root.rules
+ [ -n "$DRACUT_SYSTEMD" ] && systemctl is-active systemd-udevd && udevadm control --reload-rules
+ root=/dev/root
+
+ write_fs_tab /dev/root
+fi
+
+# If it's not empty or iscsi we don't continue
+for nroot in $(getargs netroot); do
+ [ "${nroot%%:*}" = "iscsi" ] || continue
+ netroot="$nroot"
+ break
+done
+
+# Root takes precedence over netroot
+if [ "${root}" = "/dev/root" ] && getarg "netroot=dhcp"; then
+ # if root is not specified try to mount the whole iSCSI LUN
+ printf 'ENV{DEVTYPE}!="partition", SYMLINK=="disk/by-path/*-iscsi-*-*", SYMLINK+="root"\n' >> /etc/udev/rules.d/99-iscsi-root.rules
+ [ -n "$DRACUT_SYSTEMD" ] && systemctl is-active systemd-udevd && udevadm control --reload-rules
+fi
+
+if [ -n "$iscsiroot" ]; then
+ [ -z "$netroot" ] && netroot=$root
+
+ # @deprecated
+ echo "Warning: Argument iscsiroot is deprecated and might be removed in a future"
+ echo "release. See 'man dracut.kernel' for more information."
+
+ # Accept iscsiroot argument?
+ [ -z "$netroot" ] || [ "$netroot" = "iscsi" ] \
+ || die "Argument iscsiroot only accepted for empty root= or [net]root=iscsi"
+
+ # Override root with iscsiroot content?
+ [ -z "$netroot" ] || [ "$netroot" = "iscsi" ] && netroot=iscsi:$iscsiroot
+fi
+
+# iscsi_firmware does not need argument checking
+if [ -n "$iscsi_firmware" ]; then
+ if [ "$root" != "dhcp" ] && [ "$netroot" != "dhcp" ]; then
+ [ -z "$netroot" ] && netroot=iscsi:
+ fi
+ modprobe -b -q iscsi_boot_sysfs 2> /dev/null
+ modprobe -b -q iscsi_ibft
+ # if no ip= is given, but firmware
+ echo "${DRACUT_SYSTEMD+systemctl is-active initrd-root-device.target || }[ -f '/tmp/iscsistarted-firmware' ]" > "$hookdir"/initqueue/finished/iscsi_started.sh
+ initqueue --unique --online /sbin/iscsiroot online "iscsi:" "$NEWROOT"
+ initqueue --unique --onetime --timeout /sbin/iscsiroot timeout "iscsi:" "$NEWROOT"
+ initqueue --unique --onetime --settled /sbin/iscsiroot online "iscsi:" "'$NEWROOT'"
+fi
+
+# ISCSI actually supported?
+if ! [ -e /sys/module/iscsi_tcp ]; then
+ modprobe -b -q iscsi_tcp || die "iscsiroot requested but kernel/initrd does not support iscsi"
+fi
+
+modprobe --all -b -q qla4xxx cxgb3i cxgb4i bnx2i be2iscsi
+
+if [ -n "$netroot" ] && [ "$root" != "/dev/root" ] && [ "$root" != "dhcp" ]; then
+ if ! getargbool 1 rd.neednet > /dev/null || ! getarg "ip="; then
+ initqueue --unique --onetime --settled /sbin/iscsiroot dummy "'$netroot'" "'$NEWROOT'"
+ fi
+fi
+
+if arg=$(getarg rd.iscsi.initiator -d iscsi_initiator=) && [ -n "$arg" ] && ! [ -f /run/initiatorname.iscsi ]; then
+ iscsi_initiator=$arg
+ echo "InitiatorName=$iscsi_initiator" > /run/initiatorname.iscsi
+ ln -fs /run/initiatorname.iscsi /dev/.initiatorname.iscsi
+ rm -f /etc/iscsi/initiatorname.iscsi
+ mkdir -p /etc/iscsi
+ ln -fs /run/initiatorname.iscsi /etc/iscsi/initiatorname.iscsi
+ if [ -n "$DRACUT_SYSTEMD" ]; then
+ systemctl try-restart iscsid
+ # FIXME: iscsid is not yet ready, when the service is :-/
+ sleep 1
+ fi
+fi
+
+# If not given on the cmdline and initiator-name available via iBFT
+if [ -z "$iscsi_initiator" ] && [ -f /sys/firmware/ibft/initiator/initiator-name ] && ! [ -f /tmp/iscsi_set_initiator ]; then
+ iscsi_initiator=$(while read -r line || [ -n "$line" ]; do echo "$line"; done < /sys/firmware/ibft/initiator/initiator-name)
+ if [ -n "$iscsi_initiator" ]; then
+ echo "InitiatorName=$iscsi_initiator" > /run/initiatorname.iscsi
+ rm -f /etc/iscsi/initiatorname.iscsi
+ mkdir -p /etc/iscsi
+ ln -fs /run/initiatorname.iscsi /etc/iscsi/initiatorname.iscsi
+ : > /tmp/iscsi_set_initiator
+ if [ -n "$DRACUT_SYSTEMD" ]; then
+ systemctl try-restart iscsid
+ # FIXME: iscsid is not yet ready, when the service is :-/
+ sleep 1
+ fi
+ fi
+fi
+
+if [ -z "$netroot" ] || ! [ "${netroot%%:*}" = "iscsi" ]; then
+ return 1
+fi
+
+initqueue --unique --onetime --timeout /sbin/iscsiroot timeout "$netroot" "$NEWROOT"
+
+for nroot in $(getargs netroot); do
+ [ "${nroot%%:*}" = "iscsi" ] || continue
+ type parse_iscsi_root > /dev/null 2>&1 || . /lib/net-lib.sh
+ parse_iscsi_root "$nroot" || return 1
+ netroot_enc=$(str_replace "$nroot" '/' '\2f')
+ echo "${DRACUT_SYSTEMD+systemctl is-active initrd-root-device.target || }[ -f '/tmp/iscsistarted-$netroot_enc' ]" > "$hookdir"/initqueue/finished/iscsi_started.sh
+done
+
+# Done, all good!
+# shellcheck disable=SC2034
+rootok=1
+
+# Shut up init error check
+[ -z "$root" ] && root="iscsi"
diff --git a/modules.d/95lunmask/fc_transport_scan_lun.sh b/modules.d/95lunmask/fc_transport_scan_lun.sh
new file mode 100755
index 0000000..d14d2ca
--- /dev/null
+++ b/modules.d/95lunmask/fc_transport_scan_lun.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# fc_transport_lun_scan
+#
+# Selectively enable individual LUNs behind an FC remote port
+#
+# ACTION=="add", SUBSYSTEM=="fc_transport", ATTR{port_name}=="wwpn", \
+# PROGRAM="fc_transport_lun_scan lun"
+#
+
+[ -z "$DEVPATH" ] && exit 1
+
+if [ -n "$1" ]; then
+ LUN=$1
+else
+ LUN=-
+fi
+ID=${DEVPATH##*/rport-}
+HOST=${ID%%:*}
+CHANNEL=${ID%%-*}
+CHANNEL=${CHANNEL#*:}
+if [ -f /sys"$DEVPATH"/scsi_target_id ]; then
+ read -r TARGET < /sys"$DEVPATH"/scsi_target_id
+fi
+[ -z "$TARGET" ] && exit 1
+echo "$CHANNEL" "$TARGET" $LUN > /sys/class/scsi_host/host"$HOST"/scan
diff --git a/modules.d/95lunmask/module-setup.sh b/modules.d/95lunmask/module-setup.sh
new file mode 100755
index 0000000..cf6e3d7
--- /dev/null
+++ b/modules.d/95lunmask/module-setup.sh
@@ -0,0 +1,73 @@
+#!/bin/bash
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+
+# called by dracut
+cmdline() {
+ get_lunmask() {
+ local _dev=$1
+ local _devpath _sdev _lun _rport _end_device _classdev _wwpn _sas_address
+ _devpath=$(
+ cd -P /sys/dev/block/"$_dev" || exit
+ echo "$PWD"
+ )
+
+ [ "${_devpath#*/sd}" == "$_devpath" ] && return 1
+ _sdev="${_devpath%%/block/*}"
+ _lun="${_sdev##*:}"
+ # Check for FibreChannel
+ _rport="${_devpath##*/rport-}"
+ if [ "$_rport" != "$_devpath" ]; then
+ _rport="${_rport%%/*}"
+ _classdev="/sys/class/fc_remote_ports/rport-${_rport}"
+ [ -d "$_classdev" ] || return 1
+ read -r _wwpn < "${_classdev}"/port_name
+ echo "rd.lunmask=fc,${_wwpn},${_lun}"
+ return 0
+ fi
+ # Check for SAS
+ _end_device="${_devpath##*/end_device-}"
+ if [ "$_end_device" != "$_devpath" ]; then
+ _end_device="${_end_device%%/*}"
+ _classdev="/sys/class/sas_device/end_device-${_end_device}"
+ [ -e "$_classdev" ] || return 1
+ read -r _sas_address < "${_classdev}"/sas_address
+ echo "rd.lunmask=sas,${_sas_address},${_lun}"
+ return 0
+ fi
+ return 1
+ }
+ [[ $hostonly ]] || [[ $mount_needs ]] && {
+ for_each_host_dev_and_slaves_all get_lunmask
+ } | sort | uniq
+}
+
+# called by dracut
+check() {
+ [[ $hostonly ]] || [[ $mount_needs ]] && {
+ [ -w /sys/module/scsi_mod/parameters/scan ] || return 255
+ read -r scan_type < /sys/module/scsi_mod/parameters/scan
+ [ "$scan_type" = "manual" ] && return 0
+ return 255
+ }
+ return 0
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+# called by dracut
+install() {
+ inst_script "$moddir/fc_transport_scan_lun.sh" /usr/lib/udev/fc_transport_scan_lun.sh
+ inst_script "$moddir/sas_transport_scan_lun.sh" /usr/lib/udev/sas_transport_scan_lun.sh
+ inst_hook cmdline 30 "$moddir/parse-lunmask.sh"
+ if [[ $hostonly_cmdline == "yes" ]]; then
+ local _lunmask
+
+ for _lunmask in $(cmdline); do
+ printf "%s\n" "$_lunmask" >> "${initdir}/etc/cmdline.d/95lunmask.conf"
+ done
+ fi
+}
diff --git a/modules.d/95lunmask/parse-lunmask.sh b/modules.d/95lunmask/parse-lunmask.sh
new file mode 100755
index 0000000..5e05e5b
--- /dev/null
+++ b/modules.d/95lunmask/parse-lunmask.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
+# ex: ts=8 sw=4 sts=4 et filetype=sh
+
+create_udev_rule() {
+ local transport="$1"
+ local tgtid="$2"
+ local lun="$3"
+ local _rule=/etc/udev/rules.d/51-"${transport}"-lunmask-"${tgtid}".rules
+
+ [ -e "${_rule}" ] && return 0
+
+ if [ ! -f "$_rule" ]; then
+ if [ "$transport" = "fc" ]; then
+ cat > "$_rule" << EOF
+ACTION=="add", SUBSYSTEM=="fc_remote_ports", ATTR{port_name}=="$tgtid", PROGRAM="fc_transport_scan_lun.sh $lun"
+EOF
+ elif [ "$transport" = "sas" ]; then
+ cat > "$_rule" << EOF
+ACTION=="add", SUBSYSTEM=="sas_device", ATTR{sas_address}=="$tgtid", PROGRAM="sas_transport_scan_lun.sh $lun"
+EOF
+ fi
+ fi
+}
+
+for lunmask_arg in $(getargs rd.lunmask); do
+ (
+ local OLDIFS="$IFS"
+ local IFS=","
+ # shellcheck disable=SC2086
+ set $lunmask_arg
+ IFS="$OLDIFS"
+ if [ -d /sys/module/scsi_mod ]; then
+ printf "manual" > /sys/module/scsi_mod/parameters/scan
+ elif [ ! -f /etc/modprobe.d/95lunmask.conf ]; then
+ echo "options scsi_mod scan=manual" > /etc/modprobe.d/95lunmask.conf
+ fi
+ create_udev_rule "$1" "$2" "$3"
+ )
+done
diff --git a/modules.d/95lunmask/sas_transport_scan_lun.sh b/modules.d/95lunmask/sas_transport_scan_lun.sh
new file mode 100755
index 0000000..1d1fc47
--- /dev/null
+++ b/modules.d/95lunmask/sas_transport_scan_lun.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# sas_transport_lun_scan
+#
+# Selectively enable individual LUNs behind a SAS end device
+#
+# ACTION=="add", SUBSYSTEM=="sas_transport", ATTR{sas_address}=="sas_addr", \
+# PROGRAM="sas_transport_lun_scan lun"
+#
+
+[ -z "$DEVPATH" ] && exit 1
+
+if [ -n "$1" ]; then
+ LUN=$1
+else
+ LUN=-
+fi
+ID=${DEVPATH##*/end_device-}
+HOST=${ID%%:*}
+CHANNEL=${ID%%-*}
+CHANNEL=${CHANNEL#*:}
+if [ -f /sys"$DEVPATH"/scsi_target_id ]; then
+ read -r TARGET < /sys"$DEVPATH"/scsi_target_id
+fi
+[ -z "$TARGET" ] && exit 1
+echo 0 "$TARGET" $LUN > /sys/class/scsi_host/host"$HOST"/scan
diff --git a/modules.d/95nbd/module-setup.sh b/modules.d/95nbd/module-setup.sh
new file mode 100755
index 0000000..aa3570a
--- /dev/null
+++ b/modules.d/95nbd/module-setup.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ local _rootdev
+
+ # if an nbd device is not somewhere in the chain of devices root is
+ # mounted on, fail the hostonly check.
+ [[ $hostonly ]] || [[ $mount_needs ]] && {
+ _rootdev=$(find_root_block_device)
+ [[ -b /dev/block/$_rootdev ]] || return 1
+ check_block_and_slaves block_is_nbd "$_rootdev" || return 255
+ }
+ require_binaries nbd-client || return 1
+
+ return 0
+}
+
+# called by dracut
+depends() {
+ # We depend on network modules being loaded
+ echo network rootfs-block
+}
+
+# called by dracut
+installkernel() {
+ instmods nbd
+}
+
+# called by dracut
+install() {
+ inst nbd-client
+ inst_hook cmdline 90 "$moddir/parse-nbdroot.sh"
+ inst_script "$moddir/nbdroot.sh" "/sbin/nbdroot"
+ if dracut_module_included "systemd-initrd"; then
+ inst_script "$moddir/nbd-generator.sh" "$systemdutildir"/system-generators/dracut-nbd-generator
+ fi
+ dracut_need_initqueue
+}
diff --git a/modules.d/95nbd/nbd-generator.sh b/modules.d/95nbd/nbd-generator.sh
new file mode 100755
index 0000000..38603bf
--- /dev/null
+++ b/modules.d/95nbd/nbd-generator.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+[ -z "$root" ] && root=$(getarg root=)
+
+[ "${root%%:*}" = "nbd" ] || exit 0
+
+GENERATOR_DIR="$2"
+[ -z "$GENERATOR_DIR" ] && exit 1
+
+[ -d "$GENERATOR_DIR" ] || mkdir -p "$GENERATOR_DIR"
+
+ROOTFLAGS="$(getarg rootflags)"
+
+nroot=${root#nbd:}
+nbdserver=${nroot%%:*}
+if [ "${nbdserver%"${nbdserver#?}"}" = "[" ]; then
+ nbdserver=${nroot#[}
+ nbdserver=${nbdserver%%]:*}\]
+ nroot=${nroot#*]:}
+else
+ nroot=${nroot#*:}
+fi
+nbdport=${nroot%%:*}
+nroot=${nroot#*:}
+nbdfstype=${nroot%%:*}
+nroot=${nroot#*:}
+nbdflags=${nroot%%:*}
+
+if [ "$nbdflags" = "$nbdfstype" ]; then
+ unset nbdflags
+fi
+if [ "$nbdfstype" = "$nbdport" ]; then
+ unset nbdfstype
+fi
+
+[ -n "$nbdflags" ] && ROOTFLAGS="$nbdflags"
+
+if getarg "ro"; then
+ if [ -n "$ROOTFLAGS" ]; then
+ ROOTFLAGS="$ROOTFLAGS,ro"
+ else
+ ROOTFLAGS="ro"
+ fi
+fi
+
+if [ -n "$nbdfstype" ]; then
+ ROOTFSTYPE="$nbdfstype"
+else
+ ROOTFSTYPE=$(getarg rootfstype=) || unset ROOTFSTYPE
+fi
+
+{
+ echo "[Unit]"
+ echo "Before=initrd-root-fs.target"
+ echo "[Mount]"
+ echo "Where=/sysroot"
+ echo "What=/dev/root"
+ [ -n "$ROOTFSTYPE" ] && echo "Type=${ROOTFSTYPE}"
+ [ -n "$ROOTFLAGS" ] && echo "Options=${ROOTFLAGS}"
+} > "$GENERATOR_DIR"/sysroot.mount
+
+exit 0
diff --git a/modules.d/95nbd/nbdroot.sh b/modules.d/95nbd/nbdroot.sh
new file mode 100755
index 0000000..b1a8030
--- /dev/null
+++ b/modules.d/95nbd/nbdroot.sh
@@ -0,0 +1,137 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+PATH=/usr/sbin:/usr/bin:/sbin:/bin
+
+# Huh? Empty $1?
+[ -z "$1" ] && exit 1
+
+# Huh? Empty $2?
+[ -z "$2" ] && exit 1
+
+# Huh? Empty $3?
+[ -z "$3" ] && exit 1
+
+# root is in the form root=nbd:srv:port[:fstype[:rootflags[:nbdopts]]]
+# shellcheck disable=SC2034
+netif="$1"
+nroot="$2"
+NEWROOT="$3"
+
+# If it's not nbd we don't continue
+[ "${nroot%%:*}" = "nbd" ] || return
+
+nroot=${nroot#nbd:}
+nbdserver=${nroot%%:*}
+if [ "${nbdserver%"${nbdserver#?}"}" = "[" ]; then
+ nbdserver=${nroot#[}
+ nbdserver=${nbdserver%%]:*}
+ nroot=${nroot#*]:}
+else
+ nroot=${nroot#*:}
+fi
+nbdport=${nroot%%:*}
+nroot=${nroot#*:}
+nbdfstype=${nroot%%:*}
+nroot=${nroot#*:}
+nbdflags=${nroot%%:*}
+nbdopts=${nroot#*:}
+
+if [ "$nbdopts" = "$nbdflags" ]; then
+ unset nbdopts
+fi
+if [ "$nbdflags" = "$nbdfstype" ]; then
+ unset nbdflags
+fi
+if [ "$nbdfstype" = "$nbdport" ]; then
+ unset nbdfstype
+fi
+if [ -z "$nbdfstype" ]; then
+ nbdfstype=auto
+fi
+
+# look through the NBD options and pull out the ones that need to
+# go before the host etc. Append a ',' so we know we terminate the loop
+nbdopts=${nbdopts},
+while [ -n "$nbdopts" ]; do
+ f=${nbdopts%%,*}
+ nbdopts=${nbdopts#*,}
+ if [ -z "$f" ]; then
+ break
+ fi
+ if [ -z "${f%bs=*}" -o -z "${f%timeout=*}" ]; then
+ preopts="$preopts $f"
+ continue
+ fi
+ opts="$opts $f"
+done
+
+# look through the flags and see if any are overridden by the command line
+nbdflags=${nbdflags},
+while [ -n "$nbdflags" ]; do
+ f=${nbdflags%%,*}
+ nbdflags=${nbdflags#*,}
+ if [ -z "$f" ]; then
+ break
+ fi
+ if [ "$f" = "ro" -o "$f" = "rw" ]; then
+ nbdrw=$f
+ continue
+ fi
+ fsopts=${fsopts:+$fsopts,}$f
+done
+
+getarg ro && nbdrw=ro
+getarg rw && nbdrw=rw
+fsopts=${fsopts:+$fsopts,}${nbdrw}
+
+# XXX better way to wait for the device to be made?
+i=0
+while [ ! -b /dev/nbd0 ]; do
+ [ $i -ge 20 ] && exit 1
+ udevadm settle --exit-if-exists=/dev/nbd0
+ i=$((i + 1))
+done
+
+# If we didn't get a root= on the command line, then we need to
+# add the udev rules for mounting the nbd0 device
+if [ "$root" = "block:/dev/root" -o "$root" = "dhcp" ]; then
+ printf 'KERNEL=="nbd0", ENV{DEVTYPE}!="partition", ENV{ID_FS_TYPE}=="?*", SYMLINK+="root"\n' > /etc/udev/rules.d/99-nbd-root.rules
+ udevadm control --reload
+ wait_for_dev -n /dev/root
+
+ if [ -z "$DRACUT_SYSTEMD" ]; then
+ type write_fs_tab > /dev/null 2>&1 || . /lib/fs-lib.sh
+
+ write_fs_tab /dev/root "$nbdfstype" "$fsopts"
+
+ printf '/bin/mount %s\n' \
+ "$NEWROOT" \
+ > "$hookdir"/mount/01-$$-nbd.sh
+ else
+ mkdir -p /run/systemd/system/sysroot.mount.d
+ cat << EOF > /run/systemd/system/sysroot.mount.d/dhcp.conf
+[Mount]
+Where=/sysroot
+What=/dev/root
+Type=$nbdfstype
+Options=$fsopts
+EOF
+ systemctl --no-block daemon-reload
+ fi
+ # if we're on systemd, use the nbd-generator script
+ # to create the /sysroot mount.
+fi
+
+if ! [ "$nbdport" -gt 0 ] 2> /dev/null; then
+ nbdport="-name $nbdport"
+fi
+
+if ! nbd-client -check /dev/nbd0 > /dev/null; then
+ # shellcheck disable=SC2086
+ nbd-client -p -systemd-mark "$nbdserver" $nbdport /dev/nbd0 $opts || exit 1
+fi
+
+need_shutdown
+exit 0
diff --git a/modules.d/95nbd/parse-nbdroot.sh b/modules.d/95nbd/parse-nbdroot.sh
new file mode 100755
index 0000000..1c3f0a0
--- /dev/null
+++ b/modules.d/95nbd/parse-nbdroot.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+#
+# Preferred format:
+# root=nbd:srv:port/exportname[:fstype[:rootflags[:nbdopts]]]
+# [root=*] netroot=nbd:srv:port/exportname[:fstype[:rootflags[:nbdopts]]]
+#
+# nbdopts is a comma separated list of options to give to nbd-client
+#
+# root= takes precedence over netroot= if root=nbd[...]
+#
+
+# This script is sourced, so root should be set. But let's be paranoid
+[ -z "$root" ] && root=$(getarg root=)
+
+if [ -z "$netroot" ]; then
+ for netroot in $(getargs netroot=); do
+ [ "${netroot%%:*}" = "nbd" ] && break
+ done
+ [ "${netroot%%:*}" = "nbd" ] || unset netroot
+fi
+
+# Root takes precedence over netroot
+if [ "${root%%:*}" = "nbd" ]; then
+ if [ -n "$netroot" ]; then
+ warn "root takes precedence over netroot. Ignoring netroot"
+
+ fi
+ netroot=$root
+ unset root
+fi
+
+# If it's not nbd we don't continue
+[ "${netroot%%:*}" = "nbd" ] || return
+
+# Check required arguments
+nroot=${netroot#nbd:}
+server=${nroot%%:*}
+if [ "${server%"${server#?}"}" = "[" ]; then
+ server=${nroot#[}
+ server=${server%%]:*}\]
+ nroot=${nroot#*]:}
+else
+ nroot=${nroot#*:}
+fi
+port=${nroot%%:*}
+unset nroot
+
+[ -z "$server" ] && die "Argument server for nbdroot is missing"
+[ -z "$port" ] && die "Argument port for nbdroot is missing"
+
+# NBD actually supported?
+incol2 /proc/devices nbd || modprobe nbd || die "nbdroot requested but kernel/initrd does not support nbd"
+
+# Done, all good!
+# shellcheck disable=SC2034
+rootok=1
+
+# Shut up init error check
+if [ -z "$root" ]; then
+ root=block:/dev/root
+ # the device is created and waited for in ./nbdroot.sh
+fi
+
+echo 'nbd-client -check /dev/nbd0 > /dev/null 2>&1' > "$hookdir"/initqueue/finished/nbdroot.sh
diff --git a/modules.d/95nfs/module-setup.sh b/modules.d/95nfs/module-setup.sh
new file mode 100755
index 0000000..16bafe3
--- /dev/null
+++ b/modules.d/95nfs/module-setup.sh
@@ -0,0 +1,138 @@
+#!/bin/bash
+
+# return value:
+# 'nfs4': Only nfs4 founded
+# 'nfs': nfs with version < 4 founded
+# '': No nfs founded
+get_nfs_type() {
+ local _nfs _nfs4
+
+ for fs in "${host_fs_types[@]}"; do
+ [[ $fs == "nfs" ]] && _nfs=1
+ [[ $fs == "nfs3" ]] && _nfs=1
+ [[ $fs == "nfs4" ]] && _nfs4=1
+ done
+
+ [[ "$_nfs" ]] && echo "nfs" && return
+ [[ "$_nfs4" ]] && echo "nfs4" && return
+}
+
+# called by dracut
+check() {
+ # If our prerequisites are not met, fail anyways.
+ require_any_binary rpcbind portmap || return 1
+ require_binaries rpc.statd mount.nfs mount.nfs4 umount sed chmod chown || return 1
+
+ [[ $hostonly ]] || [[ $mount_needs ]] && {
+ [[ "$(get_nfs_type)" ]] && return 0
+ return 255
+ }
+ return 0
+}
+
+# called by dracut
+depends() {
+ # We depend on network modules being loaded
+ echo network
+}
+
+# called by dracut
+installkernel() {
+ hostonly=$(optional_hostonly) instmods '=net/sunrpc' '=fs/nfs' ipv6 nfs_acl nfs_layout_nfsv41_files
+}
+
+cmdline() {
+ local nfs_device
+ local nfs_options
+ local nfs_root
+ local nfs_address
+ local lookup
+
+ ### nfsroot= ###
+ nfs_device=$(findmnt -t nfs4 -n -o SOURCE /)
+ if [ -n "$nfs_device" ]; then
+ nfs_root="root=nfs4:$nfs_device"
+ else
+ nfs_device=$(findmnt -t nfs -n -o SOURCE /)
+ [ -z "$nfs_device" ] && return
+ nfs_root="root=nfs:$nfs_device"
+ fi
+ nfs_options=$(findmnt -t nfs4,nfs -n -o OPTIONS /)
+ [ -n "$nfs_options" ] && nfs_root="$nfs_root:$nfs_options"
+ echo "$nfs_root"
+
+ ### ip= ###
+ if [[ $nfs_device =~ [0-9]*\.[0-9]*\.[0-9]*.[0-9]* ]] || [[ $nfs_device =~ \[[^]]*\] ]]; then
+ nfs_address="${nfs_device%%:*}"
+ else
+ lookup=$(host "${nfs_device%%:*}" | grep " address " | head -n1)
+ nfs_address=${lookup##* }
+ fi
+
+ [[ $nfs_address ]] || return
+ ip_params_for_remote_addr "$nfs_address"
+}
+
+# called by dracut
+install() {
+ local _nsslibs
+ inst_multiple -o rpc.idmapd mount.nfs mount.nfs4 umount sed /etc/netconfig chmod chown "$tmpfilesdir/rpcbind.conf"
+ inst_multiple -o /etc/idmapd.conf
+ inst_multiple -o /etc/services /etc/nsswitch.conf /etc/rpc /etc/protocols
+ inst_multiple -o /usr/etc/services /usr/etc/nsswitch.conf /usr/etc/rpc /usr/etc/protocols
+
+ if [[ $hostonly_cmdline == "yes" ]]; then
+ local _netconf
+ _netconf="$(cmdline)"
+ [[ $_netconf ]] && printf "%s\n" "$_netconf" >> "${initdir}/etc/cmdline.d/95nfs.conf"
+ fi
+
+ if [[ -f $dracutsysrootdir/lib/modprobe.d/nfs.conf ]]; then
+ inst_multiple /lib/modprobe.d/nfs.conf
+ else
+ [[ -d $initdir/etc/modprobe.d ]] || mkdir -p "$initdir"/etc/modprobe.d
+ echo "alias nfs4 nfs" > "$initdir"/etc/modprobe.d/nfs.conf
+ fi
+
+ inst_libdir_file 'libnfsidmap_nsswitch.so*' 'libnfsidmap/*.so' 'libnfsidmap*.so*'
+
+ _nsslibs=$(
+ cat "$dracutsysrootdir"/{,usr/}etc/nsswitch.conf 2> /dev/null \
+ | sed -e '/^#/d' -e 's/^.*://' -e 's/\[NOTFOUND=return\]//' \
+ | tr -s '[:space:]' '\n' | sort -u | tr -s '[:space:]' '|'
+ )
+ _nsslibs=${_nsslibs#|}
+ _nsslibs=${_nsslibs%|}
+
+ inst_libdir_file -n "$_nsslibs" 'libnss_*.so*'
+
+ inst_hook cmdline 90 "$moddir/parse-nfsroot.sh"
+ inst_hook pre-udev 99 "$moddir/nfs-start-rpc.sh"
+ inst_hook cleanup 99 "$moddir/nfsroot-cleanup.sh"
+ inst "$moddir/nfsroot.sh" "/sbin/nfsroot"
+
+ # For strict hostonly, only install rpcbind for NFS < 4
+ if [[ $hostonly_mode != "strict" ]] || [[ "$(get_nfs_type)" != "nfs4" ]]; then
+ inst_multiple -o portmap rpcbind rpc.statd
+ fi
+
+ inst "$moddir/nfs-lib.sh" "/lib/nfs-lib.sh"
+ mkdir -m 0755 -p "$initdir/var/lib/nfs"
+ mkdir -m 0755 -p "$initdir/var/lib/nfs/rpc_pipefs"
+ mkdir -m 0770 -p "$initdir/var/lib/rpcbind"
+ [ -d "/var/lib/nfs/statd/sm" ] && mkdir -m 0755 -p "$initdir/var/lib/nfs/statd/sm"
+ [ -d "/var/lib/nfs/sm" ] && mkdir -m 0755 -p "$initdir/var/lib/nfs/sm"
+
+ # Rather than copy the passwd file in, just set a user for rpcbind
+ # We'll save the state and restart the daemon from the root anyway
+ grep -E '^nfsnobody:|^rpc:|^rpcuser:' "$dracutsysrootdir"/etc/passwd >> "$initdir/etc/passwd"
+ grep -E '^nogroup:|^rpc:|^nobody:' "$dracutsysrootdir"/etc/group >> "$initdir/etc/group"
+
+ # rpc user needs to be able to write to this directory to save the warmstart
+ # file
+ chmod 770 "$initdir/var/lib/rpcbind"
+ grep -q '^rpc:' "$dracutsysrootdir"/etc/passwd \
+ && grep -q '^rpc:' "$dracutsysrootdir"/etc/group
+
+ dracut_need_initqueue
+}
diff --git a/modules.d/95nfs/nfs-lib.sh b/modules.d/95nfs/nfs-lib.sh
new file mode 100755
index 0000000..f000671
--- /dev/null
+++ b/modules.d/95nfs/nfs-lib.sh
@@ -0,0 +1,157 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+. /lib/net-lib.sh
+
+# TODO: make these things not pollute the calling namespace
+
+# nfs_to_var NFSROOT [NETIF]
+# use NFSROOT to set $nfs, $server, $path, and $options.
+# NFSROOT is something like: nfs[4]:<server>:/<path>[:<options>|,<options>]
+# NETIF is used to get information from DHCP options, if needed.
+nfs_to_var() {
+ # Unfortunately, there's multiple styles of nfs "URL" in use, so we need
+ # extra functions to parse them into $nfs, $server, $path, and $options.
+ # FIXME: local netif=${2:-$netif}?
+ case "$1" in
+ nfs://*) rfc2224_nfs_to_var "$1" ;;
+ nfs:*[*) anaconda_nfsv6_to_var "$1" ;;
+ nfs:*:*:/*) anaconda_nfs_to_var "$1" ;;
+ *) nfsroot_to_var "$1" ;;
+ esac
+ # if anything's missing, try to fill it in from DHCP options
+ if [ -z "$server" ] || [ -z "$path" ]; then nfsroot_from_dhcp "$2"; fi
+ # if there's a "%s" in the path, replace it with the hostname/IP
+ if strstr "$path" "%s"; then
+ local node=""
+ read -r node < /proc/sys/kernel/hostname
+ [ "$node" = "(none)" ] && node=$(get_ip "$2")
+ path=${path%%%s*}$node${path#*%s} # replace only the first %s
+ fi
+}
+
+# root=nfs:[<server-ip>:]<root-dir>[:<nfs-options>]
+# root=nfs4:[<server-ip>:]<root-dir>[:<nfs-options>]
+nfsroot_to_var() {
+ # strip nfs[4]:
+ local arg="$*:"
+ nfs="${arg%%:*}"
+ arg="${arg##"$nfs":}"
+
+ # check if we have a server
+ if strstr "$arg" ':/'; then
+ server="${arg%%:/*}"
+ arg="/${arg##*:/}"
+ fi
+
+ path="${arg%%:*}"
+
+ # rest are options
+ options="${arg##"$path"}"
+ # strip leading ":"
+ options="${options##:}"
+ # strip ":"
+ options="${options%%:}"
+
+ # Does it really start with '/'?
+ [ -n "${path%%/*}" ] && path="error"
+
+ #Fix kernel legacy style separating path and options with ','
+ if [ "$path" != "${path#*,}" ]; then
+ options=${path#*,}
+ path=${path%%,*}
+ fi
+}
+
+# RFC2224: nfs://<server>[:<port>]/<path>
+rfc2224_nfs_to_var() {
+ nfs="nfs"
+ server="${1#nfs://}"
+ path="/${server#*/}"
+ server="${server%%/*}"
+ server="${server%%:}" # anaconda compat (nfs://<server>:/<path>)
+ local port="${server##*:}"
+ [ "$port" != "$server" ] && options="port=$port"
+}
+
+# Anaconda-style path with options: nfs:<options>:<server>:/<path>
+# (without mount options, anaconda is the same as dracut)
+anaconda_nfs_to_var() {
+ nfs="nfs"
+ options="${1#nfs:}"
+ server="${options#*:}"
+ server="${server%:/*}"
+ options="${options%%:*}"
+ path="/${1##*:/}"
+}
+
+# IPv6 nfs path will be treated separately
+anaconda_nfsv6_to_var() {
+ nfs="nfs"
+ path="$1"
+ options="${path#*:/}"
+ path="/${options%%:*}"
+ server="${1#*nfs:}"
+ if str_starts "$server" '['; then
+ server="${server%:/*}"
+ options="${options#*:*}"
+ else
+ server="${server%:/*}"
+ options="${server%%:*}"
+ server="${server#*:}"
+ fi
+}
+
+# nfsroot_from_dhcp NETIF
+# fill in missing server/path from DHCP options.
+nfsroot_from_dhcp() {
+ local f
+ for f in /tmp/net.$1.override /tmp/dhclient.$1.dhcpopts; do
+ # shellcheck disable=SC1090
+ [ -f "$f" ] && . "$f"
+ done
+ [ -n "$new_root_path" ] && nfsroot_to_var "$nfs:$new_root_path"
+ [ -z "$path" ] && [ "$(getarg root=)" = "/dev/nfs" ] && path=/tftpboot/%s
+ [ -z "$server" ] && server=$srv
+ [ -z "$server" ] && server=$new_next_server
+ [ -z "$server" ] && server=$new_dhcp_server_identifier
+ [ -z "$server" ] && server=${new_root_path%%:*}
+}
+
+# Look through $options, fix "rw"/"ro", move "lock"/"nolock" to $nfslock
+munge_nfs_options() {
+ local f="" flags="" nfsrw="ro" OLDIFS="$IFS"
+ IFS=,
+ for f in $options; do
+ case $f in
+ ro | rw) nfsrw=$f ;;
+ lock | nolock) nfslock=$f ;;
+ *) flags=${flags:+$flags,}$f ;;
+ esac
+ done
+ IFS="$OLDIFS"
+
+ # Override rw/ro if set on cmdline
+ getarg ro > /dev/null && nfsrw=ro
+ getarg rw > /dev/null && nfsrw=rw
+
+ options=$nfsrw${flags:+,$flags}
+}
+
+# mount_nfs NFSROOT MNTDIR [NETIF]
+mount_nfs() {
+ local nfsroot="$1" mntdir="$2" netif="$3"
+ local nfs="" server="" path="" options=""
+ nfs_to_var "$nfsroot" "$netif"
+ munge_nfs_options
+ if [ "$nfs" = "nfs4" ]; then
+ options=$options${nfslock:+,$nfslock}
+ else
+ # NFSv{2,3} doesn't support using locks as it requires a helper to
+ # transfer the rpcbind state to the new root
+ [ "$nfslock" = "lock" ] \
+ && warn "Locks unsupported on NFSv{2,3}, using nolock" 1>&2
+ options=$options,nolock
+ fi
+ mount -t "$nfs" -o"$options" "$server:$path" "$mntdir"
+}
diff --git a/modules.d/95nfs/nfs-start-rpc.sh b/modules.d/95nfs/nfs-start-rpc.sh
new file mode 100755
index 0000000..52f6a4d
--- /dev/null
+++ b/modules.d/95nfs/nfs-start-rpc.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+if load_fstype sunrpc rpc_pipefs; then
+ [ ! -d /var/lib/nfs/rpc_pipefs/nfs ] \
+ && mount -t rpc_pipefs rpc_pipefs /var/lib/nfs/rpc_pipefs
+
+ # Start rpcbind or rpcbind
+ # FIXME occasionally saw 'rpcbind: fork failed: No such device' -- why?
+ command -v portmap > /dev/null && [ -z "$(pidof portmap)" ] && portmap
+ if command -v rpcbind > /dev/null && [ -z "$(pidof rpcbind)" ]; then
+ mkdir -p /run/rpcbind
+ chown rpc:rpc /run/rpcbind
+ rpcbind
+ fi
+
+ # Start rpc.statd as mount won't let us use locks on a NFSv4
+ # filesystem without talking to it. NFSv4 does locks internally,
+ # rpc.lockd isn't needed
+ command -v rpc.statd > /dev/null && [ -z "$(pidof rpc.statd)" ] && rpc.statd
+ command -v rpc.idmapd > /dev/null && [ -z "$(pidof rpc.idmapd)" ] && rpc.idmapd
+else
+ warn 'Kernel module "sunrpc" not in the initramfs, or support for filesystem "rpc_pipefs" missing!'
+fi
diff --git a/modules.d/95nfs/nfsroot-cleanup.sh b/modules.d/95nfs/nfsroot-cleanup.sh
new file mode 100755
index 0000000..d99519b
--- /dev/null
+++ b/modules.d/95nfs/nfsroot-cleanup.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+type incol2 > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+[ -f /tmp/nfs.rpc_pipefs_path ] && read -r rpcpipefspath < /tmp/nfs.rpc_pipefs_path
+[ -z "$rpcpipefspath" ] && rpcpipefspath=var/lib/nfs/rpc_pipefs
+
+pid=$(pidof rpc.statd)
+[ -n "$pid" ] && kill "$pid"
+
+pid=$(pidof rpc.idmapd)
+[ -n "$pid" ] && kill "$pid"
+
+pid=$(pidof rpcbind)
+[ -n "$pid" ] && kill "$pid"
+
+if incol2 /proc/mounts /var/lib/nfs/rpc_pipefs; then
+ # try to create the destination directory
+ [ -d "$NEWROOT"/$rpcpipefspath ] \
+ || mkdir -m 0755 -p "$NEWROOT"/$rpcpipefspath 2> /dev/null
+
+ if [ -d "$NEWROOT"/$rpcpipefspath ]; then
+ # mount --move does not seem to work???
+ mount --bind /var/lib/nfs/rpc_pipefs "$NEWROOT"/$rpcpipefspath
+ umount /var/lib/nfs/rpc_pipefs 2> /dev/null
+ else
+ umount /var/lib/nfs/rpc_pipefs 2> /dev/null
+ fi
+fi
diff --git a/modules.d/95nfs/nfsroot.sh b/modules.d/95nfs/nfsroot.sh
new file mode 100755
index 0000000..794e0d8
--- /dev/null
+++ b/modules.d/95nfs/nfsroot.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+. /lib/nfs-lib.sh
+
+[ "$#" = 3 ] || exit 1
+
+# root is in the form root=nfs[4]:[server:]path[:options], either from
+# cmdline or dhcp root-path
+netif="$1"
+root="$2"
+NEWROOT="$3"
+
+nfs_to_var "$root" "$netif"
+[ -z "$server" ] && die "Required parameter 'server' is missing"
+
+mount_nfs "$root" "$NEWROOT" "$netif" && {
+ [ -e /dev/root ] || ln -s null /dev/root
+ [ -e /dev/nfs ] || ln -s null /dev/nfs
+}
+
+[ -f "$NEWROOT"/etc/fstab ] && cat "$NEWROOT"/etc/fstab > /dev/null
+
+# inject new exit_if_exists
+# shellcheck disable=SC2016
+echo 'settle_exit_if_exists="--exit-if-exists=/dev/root"; rm -- "$job"' > "$hookdir"/initqueue/nfs.sh
+# force udevsettle to break
+: > "$hookdir"/initqueue/work
+
+need_shutdown
diff --git a/modules.d/95nfs/parse-nfsroot.sh b/modules.d/95nfs/parse-nfsroot.sh
new file mode 100755
index 0000000..0c8dbbb
--- /dev/null
+++ b/modules.d/95nfs/parse-nfsroot.sh
@@ -0,0 +1,128 @@
+#!/bin/sh
+#
+# Preferred format:
+# root=nfs[4]:[server:]path[:options]
+#
+# This syntax can come from DHCP root-path as well.
+#
+# Legacy format:
+# root=/dev/nfs nfsroot=[server:]path[,options]
+#
+# In Legacy root=/dev/nfs mode, if the 'nfsroot' parameter is not given
+# on the command line or is empty, the dhcp root-path is used as
+# [server:]path[:options] or the default "/tftpboot/%s" will be used.
+#
+# If server is unspecified it will be pulled from one of the following
+# sources, in order:
+# static ip= option on kernel command line
+# DHCP next-server option
+# DHCP server-id option
+# DHCP root-path option
+#
+# NFSv4 is only used if explicitly requested with nfs4: prefix, otherwise
+# NFSv3 is used.
+#
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+. /lib/nfs-lib.sh
+
+# This script is sourced, so root should be set. But let's be paranoid
+[ -z "$root" ] && root=$(getarg root=)
+[ -z "$nfsroot" ] && nfsroot=$(getarg nfsroot=)
+
+[ -n "$netroot" ] && oldnetroot="$netroot"
+
+# netroot= cmdline argument must be ignored, but must be used if
+# we're inside netroot to parse dhcp root-path
+if [ -n "$netroot" ]; then
+ for n in $(getargs netroot=); do
+ [ "$n" = "$netroot" ] && break
+ done
+ if [ "$n" = "$netroot" ]; then
+ #warn "Ignoring netroot argument for NFS"
+ netroot=$root
+ fi
+else
+ netroot=$root
+fi
+
+# LEGACY: nfsroot= is valid only if root=/dev/nfs
+if [ -n "$nfsroot" ]; then
+ # @deprecated
+ warn "Argument nfsroot is deprecated and might be removed in a future release. See 'man dracut.kernel' for more information."
+ if [ "$(getarg root=)" != "/dev/nfs" ]; then
+ die "Argument nfsroot only accepted for legacy root=/dev/nfs"
+ fi
+ netroot=nfs:$nfsroot
+fi
+
+case "$netroot" in
+ /dev/nfs) netroot=nfs ;;
+ /dev/*)
+ if [ -n "$oldnetroot" ]; then
+ netroot="$oldnetroot"
+ else
+ unset netroot
+ fi
+ return
+ ;;
+ # LEGACY: root=<server-ip>:/<path
+ [0-9]*:/* | [0-9]*\.[0-9]*\.[0-9]*[!:] | /*)
+ netroot=nfs:$netroot
+ ;;
+esac
+
+# Continue if nfs
+case "${netroot%%:*}" in
+ nfs | nfs4 | /dev/nfs) ;;
+ *)
+ if [ -n "$oldnetroot" ]; then
+ netroot="$oldnetroot"
+ else
+ unset netroot
+ fi
+ return
+ ;;
+esac
+
+# Check required arguments
+
+if nfsdomain=$(getarg rd.nfs.domain -d rd_NFS_DOMAIN); then
+ if [ -f /etc/idmapd.conf ]; then
+ sed -i -e \
+ "s/^[[:space:]#]*Domain[[:space:]]*=.*/Domain = $nfsdomain/g" \
+ /etc/idmapd.conf
+ fi
+ # and even again after the sed, in case it was not yet specified
+ echo "Domain = $nfsdomain" >> /etc/idmapd.conf
+fi
+
+nfsroot_to_var "$netroot"
+[ "$path" = "error" ] && die "Argument nfsroot must contain a valid path!"
+
+# Set fstype, might help somewhere
+fstype=${nfs#/dev/}
+
+# Rewrite root so we don't have to parse this ugliness later on again
+netroot="$fstype:$server:$path:$options"
+
+# If we don't have a server, we need dhcp
+if [ -z "$server" ]; then
+ # shellcheck disable=SC2034
+ DHCPORSERVER="1"
+fi
+
+# Done, all good!
+# shellcheck disable=SC2034
+rootok=1
+
+# Shut up init error check or make sure that block parser won't get
+# confused by having /dev/nfs[4]
+root="$fstype"
+
+# shellcheck disable=SC2016
+echo '[ -e $NEWROOT/proc ]' > "$hookdir"/initqueue/finished/nfsroot.sh
+
+mkdir -p /var/lib/rpcbind
+chown rpc:rpc /var/lib/rpcbind
+chmod 770 /var/lib/rpcbind
diff --git a/modules.d/95nvmf/95-nvmf-initqueue.rules b/modules.d/95nvmf/95-nvmf-initqueue.rules
new file mode 100644
index 0000000..d26d7b0
--- /dev/null
+++ b/modules.d/95nvmf/95-nvmf-initqueue.rules
@@ -0,0 +1,10 @@
+#
+# nvmf-initqueue.rules
+#
+# D-Bus doesn't run in the initrd, which means that we cannot use our
+# usual trick of starting custom systemd services.
+# So use a rule to create initqueue entries instead.
+
+ACTION=="change", SUBSYSTEM=="fc", ENV{FC_EVENT}=="nvmediscovery", \
+ ENV{NVMEFC_HOST_TRADDR}=="*", ENV{NVMEFC_TRADDR}=="*", \
+ RUN+="/sbin/initqueue --onetime --unique --name nvmf-connect-$env{NVMEFC_TRADDR}-$env{NVMEFC_HOST_TRADDR} /usr/sbin/nvme connect-all --transport=fc --traddr=$env{NVMEFC_TRADDR} --host-traddr=$env{NVMEFC_HOST_TRADDR}"
diff --git a/modules.d/95nvmf/module-setup.sh b/modules.d/95nvmf/module-setup.sh
new file mode 100755
index 0000000..a8f3034
--- /dev/null
+++ b/modules.d/95nvmf/module-setup.sh
@@ -0,0 +1,148 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ require_binaries nvme jq || return 1
+ [ -f /etc/nvme/hostnqn ] || return 255
+ [ -f /etc/nvme/hostid ] || return 255
+
+ is_nvmf() {
+ local _dev=$1
+ local trtype
+
+ [[ -L "/sys/dev/block/$_dev" ]] || return 0
+ cd -P "/sys/dev/block/$_dev" || return 0
+ if [ -f partition ]; then
+ cd ..
+ fi
+ for d in device/nvme*; do
+ [ -L "$d" ] || continue
+ if readlink "$d" | grep -q nvme-fabrics; then
+ read -r trtype < "$d"/transport
+ break
+ fi
+ done
+ [[ $trtype == "fc" ]] || [[ $trtype == "tcp" ]] || [[ $trtype == "rdma" ]]
+ }
+
+ has_nbft() {
+ local f found=
+ for f in /sys/firmware/acpi/tables/NBFT*; do
+ [ -f "$f" ] || continue
+ found=1
+ break
+ done
+ [[ $found ]]
+ }
+
+ [[ $hostonly ]] || [[ $mount_needs ]] && {
+ pushd . > /dev/null
+ for_each_host_dev_and_slaves is_nvmf
+ local _is_nvmf=$?
+ popd > /dev/null || exit
+ [[ $_is_nvmf == 0 ]] || return 255
+ if [ ! -f /sys/class/fc/fc_udev_device/nvme_discovery ] \
+ && [ ! -f /etc/nvme/discovery.conf ] \
+ && [ ! -f /etc/nvme/config.json ] && ! has_nbft; then
+ echo "No discovery arguments present"
+ return 255
+ fi
+ }
+ return 0
+}
+
+# called by dracut
+depends() {
+ echo bash rootfs-block network
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ instmods nvme_fc lpfc qla2xxx
+ hostonly="" instmods nvme_tcp nvme_fabrics 8021q
+}
+
+# called by dracut
+cmdline() {
+ local _hostnqn
+ local _hostid
+
+ gen_nvmf_cmdline() {
+ local _dev=$1
+ local trtype
+ local traddr
+ local host_traddr
+ local trsvcid
+ local _address
+ local -a _address_parts
+
+ [[ -L "/sys/dev/block/$_dev" ]] || return 0
+ cd -P "/sys/dev/block/$_dev" || return 0
+ if [ -f partition ]; then
+ cd ..
+ fi
+ for d in device/nvme*; do
+ [ -L "$d" ] || continue
+ if readlink "$d" | grep -q nvme-fabrics; then
+ read -r trtype < "$d"/transport
+ break
+ fi
+ done
+
+ [ -z "$trtype" ] && return 0
+ nvme list-subsys "${PWD##*/}" | while read -r _ _ trtype _address _; do
+ [[ -z $trtype || $trtype != "${trtype#NQN}" ]] && continue
+ unset traddr
+ unset host_traddr
+ unset trsvcid
+ mapfile -t -d ',' _address_parts < <(printf "%s" "$_address")
+ for i in "${_address_parts[@]}"; do
+ [[ $i =~ ^traddr= ]] && traddr="${i#traddr=}"
+ [[ $i =~ ^host_traddr= ]] && host_traddr="${i#host_traddr=}"
+ [[ $i =~ ^trsvcid= ]] && trsvcid="${i#trsvcid=}"
+ done
+ [[ -z $traddr && -z $host_traddr && -z $trsvcid ]] && continue
+ echo -n " rd.nvmf.discover=$trtype,$traddr,$host_traddr,$trsvcid"
+ done
+ }
+
+ if [ -f /etc/nvme/hostnqn ]; then
+ read -r _hostnqn < /etc/nvme/hostnqn
+ echo -n " rd.nvmf.hostnqn=${_hostnqn}"
+ fi
+ if [ -f /etc/nvme/hostid ]; then
+ read -r _hostid < /etc/nvme/hostid
+ echo -n " rd.nvmf.hostid=${_hostid}"
+ fi
+
+ [[ $hostonly ]] || [[ $mount_needs ]] && {
+ pushd . > /dev/null
+ for_each_host_dev_and_slaves gen_nvmf_cmdline
+ popd > /dev/null || exit
+ }
+}
+
+# called by dracut
+install() {
+ if [[ $hostonly_cmdline == "yes" ]]; then
+ local _nvmf_args
+ _nvmf_args=$(cmdline)
+ [[ "$_nvmf_args" ]] && printf "%s" "$_nvmf_args" >> "${initdir}/etc/cmdline.d/95nvmf-args.conf"
+ fi
+ inst_simple "/etc/nvme/hostnqn"
+ inst_simple "/etc/nvme/hostid"
+
+ inst_multiple ip sed
+
+ inst_script "${moddir}/nvmf-autoconnect.sh" /sbin/nvmf-autoconnect.sh
+ inst_script "${moddir}/nbftroot.sh" /sbin/nbftroot
+
+ inst_multiple nvme jq
+ inst_hook cmdline 92 "$moddir/parse-nvmf-boot-connections.sh"
+ inst_simple "/etc/nvme/discovery.conf"
+ inst_simple "/etc/nvme/config.json"
+ inst_rules /usr/lib/udev/rules.d/71-nvmf-iopolicy-netapp.rules
+ inst_rules "$moddir/95-nvmf-initqueue.rules"
+ dracut_need_initqueue
+}
diff --git a/modules.d/95nvmf/nbftroot.sh b/modules.d/95nvmf/nbftroot.sh
new file mode 100755
index 0000000..0f33499
--- /dev/null
+++ b/modules.d/95nvmf/nbftroot.sh
@@ -0,0 +1,5 @@
+#! /bin/sh
+# This script is called from /sbin/netroot
+
+/sbin/nvmf-autoconnect.sh online
+exit 0
diff --git a/modules.d/95nvmf/nvmf-autoconnect.sh b/modules.d/95nvmf/nvmf-autoconnect.sh
new file mode 100755
index 0000000..35ee948
--- /dev/null
+++ b/modules.d/95nvmf/nvmf-autoconnect.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+# Argument $1 is "settled", "online", or "timeout", indicating
+# the queue from which the script is called.
+# In the "timeout" case, try everything.
+# Otherwise, try options according to the priorities below.
+
+[ "$RD_DEBUG" != yes ] || set -x
+
+if [ "$1" = timeout ]; then
+ [ ! -f /sys/class/fc/fc_udev_device/nvme_discovery ] \
+ || echo add > /sys/class/fc/fc_udev_device/nvme_discovery
+ /usr/sbin/nvme connect-all
+ exit 0
+fi
+
+NVMF_HOSTNQN_OK=
+[ ! -f "/etc/nvme/hostnqn" ] || [ ! -f "/etc/nvme/hostid" ] || NVMF_HOSTNQN_OK=1
+
+# Only nvme-cli 2.5 or newer supports the options --nbft and --no-nbft
+# for the connect-all command.
+# Make sure we don't use unsupported options with earlier versions.
+NBFT_SUPPORTED=
+# shellcheck disable=SC2016
+/usr/sbin/nvme connect-all --help 2>&1 | sed -n '/[[:space:]]--nbft[[:space:]]/q1;$q0' \
+ || NBFT_SUPPORTED=1
+
+if [ -e /tmp/nvmf-fc-auto ] && [ "$NVMF_HOSTNQN_OK" ] \
+ && [ -f /sys/class/fc/fc_udev_device/nvme_discovery ]; then
+ # prio 1: cmdline override "rd.nvmf.discovery=fc,auto"
+ echo add > /sys/class/fc/fc_udev_device/nvme_discovery
+ exit 0
+fi
+if [ "$NBFT_SUPPORTED" ] && [ -e /tmp/valid_nbft_entry_found ]; then
+ # prio 2: NBFT
+ /usr/sbin/nvme connect-all --nbft
+ exit 0
+fi
+if [ -f /etc/nvme/discovery.conf ] || [ -f /etc/nvme/config.json ] \
+ && [ "$NVMF_HOSTNQN_OK" ]; then
+ # prio 3: configuration from initrd and/or kernel command line
+ # We can get here even if "rd.nvmf.nonbft" was given, thus use --no-nbft
+ if [ "$NBFT_SUPPORTED" ]; then
+ /usr/sbin/nvme connect-all --no-nbft
+ else
+ /usr/sbin/nvme connect-all
+ fi
+ exit 0
+fi
+if [ "$NVMF_HOSTNQN_OK" ] \
+ && [ -f /sys/class/fc/fc_udev_device/nvme_discovery ]; then
+ # prio 4: no discovery entries, try NVMeoFC autoconnect
+ echo add > /sys/class/fc/fc_udev_device/nvme_discovery
+fi
+exit 0
diff --git a/modules.d/95nvmf/parse-nvmf-boot-connections.sh b/modules.d/95nvmf/parse-nvmf-boot-connections.sh
new file mode 100755
index 0000000..6601837
--- /dev/null
+++ b/modules.d/95nvmf/parse-nvmf-boot-connections.sh
@@ -0,0 +1,326 @@
+#!/bin/sh
+#
+# Supported formats:
+# rd.nvmf.hostnqn=<hostnqn>
+# rd.nvmf.hostid=<hostid>
+# rd.nvmf.discover=<transport>,<traddr>,<host-traddr>,<trsvcid>
+#
+# Examples:
+# rd.nvmf.hostnqn=nqn.2014-08.org.nvmexpress:uuid:37303738-3034-584d-5137-333230423843
+# rd.nvmf.discover=rdma,192.168.1.3,,4420
+# rd.nvmf.discover=tcp,192.168.1.3,,4420
+# rd.nvmf.discover=tcp,192.168.1.3
+# rd.nvmf.discover=fc,nn-0x200400a098d85236:pn-0x201400a098d85236,nn-0x200000109b7db455:pn-0x100000109b7db455
+# rd.nvmf.discover=fc,auto
+#
+# Note: FC does autodiscovery, so typically there is no need to
+# specify any discover parameters for FC.
+#
+
+command -v getarg > /dev/null || . /lib/dracut-lib.sh
+command -v is_ip > /dev/null || . /lib/net-lib.sh
+
+## Sample NBFT output from nvme show-nbft -H -s -d -o json
+# [
+# {
+# "filename":"/sys/firmware/acpi/tables/NBFT",
+# "host":{
+# "nqn":"nqn.2014-08.org.nvmexpress:uuid:d6f07002-7eb5-4841-a185-400e296afae4",
+# "id":"111919da-21ea-cc4e-bafe-216d8372dd31",
+# "host_id_configured":0,
+# "host_nqn_configured":0,
+# "primary_admin_host_flag":"not indicated"
+# },
+# "subsystem":[
+# {
+# "index":1,
+# "num_hfis":1,
+# "hfis":[
+# 1
+# ],
+# "transport":"tcp",
+# "transport_address":"192.168.100.216",
+# "transport_svcid":"4420",
+# "subsys_port_id":0,
+# "nsid":1,
+# "nid_type":"uuid",
+# "nid":"424d1c8a-8ef9-4681-b2fc-8c343bd8fa69",
+# "subsys_nqn":"timberland-01",
+# "controller_id":0,
+# "asqsz":0,
+# "pdu_header_digest_required":0,
+# "data_digest_required":0
+# }
+# ],
+# "hfi":[
+# {
+# "index":1,
+# "transport":"tcp",
+# "pcidev":"0:0:2.0",
+# "mac_addr":"52:54:00:4f:97:e9",
+# "vlan":0,
+# "ip_origin":63,
+# "ipaddr":"192.168.100.217",
+# "subnet_mask_prefix":24,
+# "gateway_ipaddr":"0.0.0.0",
+# "route_metric":0,
+# "primary_dns_ipaddr":"0.0.0.0",
+# "secondary_dns_ipaddr":"0.0.0.0",
+# "dhcp_server_ipaddr":"",
+# "this_hfi_is_default_route":1
+# }
+# ],
+# "discovery":[
+# ]
+# }
+# ]
+#
+# If the IP address is derived from DHCP, it sets the field
+# "hfi.dhcp_server_ipaddr" to a non-emtpy value.
+#
+#
+
+nbft_run_jq() {
+ local st
+ local opts="-e"
+
+ while [ $# -gt 0 ]; do
+ case $1 in
+ -*)
+ opts="$opts $1"
+ ;;
+ *)
+ break
+ ;;
+ esac
+ shift
+ done
+ # Not quoting is intentional here. We won't get glob expressions passed.
+ # shellcheck disable=SC2086
+ jq $opts "$1" << EOF
+$2
+EOF
+ st=$?
+ if [ $st -ne 0 ]; then
+ warn "NBFT: jq error while processing \"$1\""
+ return $st
+ else
+ return 0
+ fi
+}
+
+nbft_check_empty_address() {
+ # suppress meaningless or empty IP addresses
+ # "null" is returned by jq if no match found for expression
+ case $1 in
+ null | "::" | "0.0.0.0") ;;
+ *)
+ echo "$1"
+ ;;
+ esac
+}
+
+nbft_parse_hfi() {
+ # false positive of shellcheck - no expansion in variable assignments
+ # shellcheck disable=2086
+ local hfi_json=$1
+ local mac iface ipaddr prefix vlan gateway dns1 dns2 hostname adrfam dhcp
+
+ mac=$(nbft_run_jq -r .mac_addr "$hfi_json") || return 1
+ iface=$(set_ifname nbft "$mac")
+
+ vlan=$(nbft_run_jq .vlan "$hfi_json") || vlan=0
+ # treat VLAN zero as "no vlan"
+ [ "$vlan" -ne 0 ] || vlan=
+
+ [ ! -e /tmp/net."${iface}${vlan:+.$vlan}".has_ibft_config ] || return 0
+
+ dhcp=$(nbft_run_jq -r .dhcp_server_ipaddr "$hfi_json")
+ # We need to check $? here as the above is an assignment
+ # shellcheck disable=2181
+ if [ $? -eq 0 ] && [ "$dhcp" ] && [ "$dhcp" != null ]; then
+ case $dhcp in
+ *:*)
+ echo ip="$iface${vlan:+.$vlan}:dhcp6"
+ ;;
+ *.*.*.*)
+ echo ip="$iface${vlan:+.$vlan}:dhcp"
+ ;;
+ *)
+ warn "Invalid value for dhcp_server_ipaddr: $dhcp"
+ return 1
+ ;;
+ esac
+ else
+ ipaddr=$(nbft_run_jq -r .ipaddr "$hfi_json") || return 1
+
+ case $ipaddr in
+ *.*.*.*)
+ adrfam=ipv4
+ ;;
+ *:*)
+ adrfam=ipv6
+ ;;
+ *)
+ warn "invalid address: $ipaddr"
+ return 1
+ ;;
+ esac
+ prefix=$(nbft_run_jq -r .subnet_mask_prefix "$hfi_json")
+ # Need to check $? here as he above is an assignment
+ # shellcheck disable=2181
+ if [ $? -ne 0 ] && [ "$adrfam" = ipv6 ]; then
+ prefix=128
+ fi
+ # Use brackets for IPv6
+ if [ "$adrfam" = ipv6 ]; then
+ ipaddr="[$ipaddr]"
+ fi
+
+ gateway=$(nbft_check_empty_address \
+ "$(nbft_run_jq -r .gateway_ipaddr "$hfi_json")")
+ dns1=$(nbft_check_empty_address \
+ "$(nbft_run_jq -r .primary_dns_ipaddr "$hfi_json")")
+ dns2=$(nbft_check_empty_address \
+ "$(nbft_run_jq -r .secondary_dns_ipaddr "$hfi_json")")
+ hostname=$(nbft_run_jq -r .host_name "$hfi_json" 2> /dev/null) || hostname=
+
+ echo "ip=$ipaddr::$gateway:$prefix:$hostname:$iface${vlan:+.$vlan}:none${dns1:+:$dns1}${dns2:+:$dns2}"
+ fi
+
+ if [ "$vlan" ]; then
+ echo "vlan=$iface.$vlan:$iface"
+ echo "$mac" > "/tmp/net.$iface.$vlan.has_ibft_config"
+ else
+ echo "$mac" > "/tmp/net.$iface.has_ibft_config"
+ fi
+ : > /tmp/valid_nbft_entry_found
+}
+
+nbft_parse() {
+ local nbft_json n_nbft all_hfi_json n_hfi
+ local j=0 i
+
+ nbft_json=$(nvme nbft show -H -o json) || return 0
+ n_nbft=$(nbft_run_jq ". | length" "$nbft_json") || return 0
+
+ while [ "$j" -lt "$n_nbft" ]; do
+ all_hfi_json=$(nbft_run_jq ".[$j].hfi" "$nbft_json") || continue
+ n_hfi=$(nbft_run_jq ". | length" "$all_hfi_json") || continue
+ i=0
+
+ while [ "$i" -lt "$n_hfi" ]; do
+ nbft_parse_hfi "$(nbft_run_jq ".[$i]" "$all_hfi_json")"
+ i=$((i + 1))
+ done
+ j=$((j + 1))
+ done >> /etc/cmdline.d/40-nbft.conf
+}
+
+if getargbool 0 rd.nonvmf; then
+ warn "rd.nonvmf=0: skipping nvmf"
+ return 0
+fi
+
+if getargbool 0 rd.nvmf.nostatic; then
+ rm -f /etc/cmdline.d/95nvmf-args.conf
+ rm -f /etc/nvme/discovery.conf /etc/nvme/config.json
+fi
+
+if ! getargbool 0 rd.nvmf.nonbft; then
+ for _x in /sys/firmware/acpi/tables/NBFT*; do
+ if [ -f "$_x" ]; then
+ nbft_parse
+ break
+ fi
+ done
+fi
+
+initqueue --onetime modprobe --all -b -q nvme_tcp nvme_core nvme_fabrics
+
+parse_nvmf_discover() {
+ traddr="none"
+ trtype="none"
+ hosttraddr="none"
+ trsvcid=4420
+ OLDIFS="$IFS"
+ IFS=,
+ # shellcheck disable=SC2086
+ set -- $1
+ IFS="$OLDIFS"
+
+ case $# in
+ 2)
+ [ -n "$1" ] && trtype=$1
+ [ -n "$2" ] && traddr=$2
+ ;;
+ 3)
+ [ -n "$1" ] && trtype=$1
+ [ -n "$2" ] && traddr=$2
+ [ -n "$3" ] && hosttraddr=$3
+ ;;
+ 4)
+ [ -n "$1" ] && trtype=$1
+ [ -n "$2" ] && traddr=$2
+ [ -n "$3" ] && hosttraddr=$3
+ [ -n "$4" ] && trsvcid=$4
+ ;;
+ *)
+ warn "Invalid arguments for rd.nvmf.discover=$1"
+ return 0
+ ;;
+ esac
+ if [ "$traddr" = "none" ]; then
+ warn "traddr is mandatory for $trtype"
+ return 0
+ fi
+ if [ "$trtype" = "tcp" ]; then
+ : > /tmp/nvmf_needs_network
+ elif [ "$trtype" = "fc" ]; then
+ if [ "$traddr" = "auto" ]; then
+ rm -f /etc/nvme/discovery.conf /etc/nvme/config.json
+ return 1
+ fi
+ if [ "$hosttraddr" = "none" ]; then
+ warn "host traddr is mandatory for fc"
+ return 0
+ fi
+ elif [ "$trtype" != "rdma" ]; then
+ warn "unsupported transport $trtype"
+ return 0
+ fi
+ if [ "$trtype" = "fc" ]; then
+ echo "--transport=$trtype --traddr=$traddr --host-traddr=$hosttraddr" >> /etc/nvme/discovery.conf
+ else
+ echo "--transport=$trtype --traddr=$traddr --host-traddr=$hosttraddr --trsvcid=$trsvcid" >> /etc/nvme/discovery.conf
+ fi
+ return 0
+}
+
+nvmf_hostnqn=$(getarg rd.nvmf.hostnqn -d nvmf.hostnqn=)
+if [ -n "$nvmf_hostnqn" ]; then
+ echo "$nvmf_hostnqn" > /etc/nvme/hostnqn
+fi
+nvmf_hostid=$(getarg rd.nvmf.hostid -d nvmf.hostid=)
+if [ -n "$nvmf_hostid" ]; then
+ echo "$nvmf_hostid" > /etc/nvme/hostid
+fi
+
+rm -f /tmp/nvmf-fc-auto
+for d in $(getargs rd.nvmf.discover -d nvmf.discover=); do
+ parse_nvmf_discover "$d" || {
+ : > /tmp/nvmf-fc-auto
+ break
+ }
+done
+
+if [ -e /tmp/nvmf_needs_network ] || [ -e /tmp/valid_nbft_entry_found ]; then
+ echo "rd.neednet=1" > /etc/cmdline.d/nvmf-neednet.conf
+ # netroot is a global variable that is present in all "sourced" scripts
+ # shellcheck disable=SC2034
+ netroot=nbft
+ rm -f /tmp/nvmf_needs_network
+fi
+
+/sbin/initqueue --settled --onetime --name nvmf-connect-settled /sbin/nvmf-autoconnect.sh settled
+/sbin/initqueue --timeout --onetime --name nvmf-connect-timeout /sbin/nvmf-autoconnect.sh timeout
diff --git a/modules.d/95qeth_rules/module-setup.sh b/modules.d/95qeth_rules/module-setup.sh
new file mode 100755
index 0000000..a84ac15
--- /dev/null
+++ b/modules.d/95qeth_rules/module-setup.sh
@@ -0,0 +1,58 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ local _arch=${DRACUT_ARCH:-$(uname -m)}
+ local _online=0
+ [ "$_arch" = "s390" -o "$_arch" = "s390x" ] || return 1
+ dracut_module_included network || return 1
+
+ [[ $hostonly ]] && {
+ for i in /sys/devices/qeth/*/online; do
+ [ ! -f "$i" ] && continue
+ read -r _online < "$i"
+ [ "$_online" -eq 1 ] && return 0
+ done
+ }
+ return 255
+}
+
+# called by dracut
+installkernel() {
+ instmods qeth
+}
+
+# called by dracut
+install() {
+ ccwid() {
+ qeth_path=$(readlink -e -q "$1"/device)
+ basename "$qeth_path"
+ }
+
+ inst_rules_qeth() {
+ for rule in /etc/udev/rules.d/{4,5}1-qeth-${1}.rules; do
+ # prefer chzdev generated 41- rules
+ if [ -f "$rule" ]; then
+ inst_rules "$rule"
+ break
+ fi
+ done
+ }
+
+ has_carrier() {
+ carrier=0
+ # not readable in qeth interfaces
+ # that have just been assembled, ignore
+ # read error and assume no carrier
+ read -r carrier 2> /dev/null < "$1/carrier"
+ [ "$carrier" -eq 1 ] && return 0
+ return 1
+ }
+
+ for dev in /sys/class/net/*; do
+ has_carrier "$dev" || continue
+ id=$(ccwid "$dev")
+ [ -n "$id" ] && inst_rules_qeth "$id"
+ done
+
+}
diff --git a/modules.d/95resume/module-setup.sh b/modules.d/95resume/module-setup.sh
new file mode 100755
index 0000000..d255103
--- /dev/null
+++ b/modules.d/95resume/module-setup.sh
@@ -0,0 +1,68 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ swap_on_netdevice() {
+ local _dev
+ for _dev in "${swap_devs[@]}"; do
+ block_is_netdevice "$(get_maj_min "$_dev")" && return 0
+ done
+ return 1
+ }
+
+ # Only support resume if hibernation is currently on
+ # and no swap is mounted on a net device
+ [[ $hostonly ]] || [[ $mount_needs ]] && {
+ swap_on_netdevice || [[ -f /sys/power/resume && "$(< /sys/power/resume)" == "0:0" ]] || grep -rq '^\|[[:space:]]resume=' /proc/cmdline /etc/cmdline /etc/cmdline.d /etc/kernel/cmdline /usr/lib/kernel/cmdline 2> /dev/null && return 255
+ }
+
+ return 0
+}
+
+# called by dracut
+cmdline() {
+ local _resume
+
+ for dev in "${!host_fs_types[@]}"; do
+ [[ ${host_fs_types[$dev]} =~ ^(swap|swsuspend|swsupend)$ ]] || continue
+ _resume=$(shorten_persistent_dev "$(get_persistent_dev "$dev")")
+ [[ -n ${_resume} ]] && printf " resume=%s" "${_resume}"
+ done
+}
+
+# called by dracut
+install() {
+ local _bin
+ local _resumeconf
+
+ if [[ $hostonly_cmdline == "yes" ]]; then
+ _resumeconf=$(cmdline)
+ [[ $_resumeconf ]] && printf "%s\n" "$_resumeconf" >> "${initdir}/etc/cmdline.d/95resume.conf"
+ fi
+
+ # if systemd is included and has the hibernate-resume tool, use it and nothing else
+ if dracut_module_included "systemd" && [[ -x $dracutsysrootdir$systemdutildir/systemd-hibernate-resume ]]; then
+ inst_multiple -o \
+ "$systemdutildir"/system-generators/systemd-hibernate-resume-generator \
+ "$systemdsystemunitdir"/systemd-hibernate-resume@.service \
+ "$systemdutildir"/systemd-hibernate-resume
+ return 0
+ fi
+
+ # Optional uswsusp support
+ for _bin in /usr/sbin/resume /usr/lib/suspend/resume /usr/lib64/suspend/resume /usr/lib/uswsusp/resume /usr/lib64/uswsusp/resume; do
+ [[ -x $dracutsysrootdir${_bin} ]] && {
+ inst "${_bin}" /usr/sbin/resume
+ [[ $hostonly ]] && [[ -f $dracutsysrootdir/etc/suspend.conf ]] && inst -H /etc/suspend.conf
+ break
+ }
+ done
+
+ if ! dracut_module_included "systemd"; then
+ inst_hook cmdline 10 "$moddir/parse-resume.sh"
+ else
+ inst_script "$moddir/parse-resume.sh" /lib/dracut/parse-resume.sh
+ fi
+
+ inst_script "$moddir/resume.sh" /lib/dracut/resume.sh
+}
diff --git a/modules.d/95resume/parse-resume.sh b/modules.d/95resume/parse-resume.sh
new file mode 100755
index 0000000..75a905d
--- /dev/null
+++ b/modules.d/95resume/parse-resume.sh
@@ -0,0 +1,81 @@
+#!/bin/sh
+
+if resume=$(getarg resume=) && ! getarg noresume; then
+ export resume
+ echo "$resume" > /.resume
+else
+ unset resume
+fi
+
+resume="$(label_uuid_to_dev "$resume")"
+
+if splash=$(getarg splash=); then
+ export splash
+else
+ unset splash
+fi
+
+case "$splash" in
+ quiet)
+ a_splash="-P splash=y"
+ ;;
+ *)
+ a_splash="-P splash=n"
+ ;;
+esac
+
+if ! getarg noresume; then
+ if [ -n "$resume" ]; then
+ wait_for_dev /dev/resume
+
+ {
+ printf "KERNEL==\"%s\", ACTION==\"add|change\", SYMLINK+=\"resume\"\n" \
+ "${resume#/dev/}"
+ printf "SYMLINK==\"%s\", ACTION==\"add|change\", SYMLINK+=\"resume\"\n" \
+ "${resume#/dev/}"
+ } >> /etc/udev/rules.d/99-resume-link.rules
+
+ {
+ if [ -x /usr/sbin/resume ]; then
+ printf -- 'KERNEL=="%s", ' "${resume#/dev/}"
+ printf -- '%s' 'ACTION=="add|change", ENV{ID_FS_TYPE}=="suspend|swsuspend|swsupend",'
+ printf -- " RUN+=\"/sbin/initqueue --finished --unique --name 00resume /usr/sbin/resume %s \'%s\'\"\n" \
+ "$a_splash" "$resume"
+ printf -- 'SYMLINK=="%s", ' "${resume#/dev/}"
+ printf -- '%s' 'ACTION=="add|change", ENV{ID_FS_TYPE}=="suspend|swsuspend|swsupend",'
+ printf -- " RUN+=\"/sbin/initqueue --finished --unique --name 00resume /usr/sbin/resume %s \'%s\'\"\n" \
+ "$a_splash" "$resume"
+ fi
+
+ printf -- 'KERNEL=="%s", ' "${resume#/dev/}"
+ printf -- '%s' 'ACTION=="add|change", ENV{ID_FS_TYPE}=="suspend|swsuspend|swsupend",'
+ printf -- '%s\n' ' RUN+="/sbin/initqueue --finished --unique --name 00resume echo %M:%m > /sys/power/resume"'
+
+ printf -- 'SYMLINK=="%s", ' "${resume#/dev/}"
+ printf -- '%s' 'ACTION=="add|change", ENV{ID_FS_TYPE}=="suspend|swsuspend|swsupend",'
+ printf -- '%s\n' ' RUN+="/sbin/initqueue --finished --unique --name 00resume echo %M:%m > /sys/power/resume"'
+ } >> /etc/udev/rules.d/99-resume.rules
+
+ # shellcheck disable=SC2016
+ printf '[ -e "%s" ] && { ln -fs "%s" /dev/resume 2> /dev/null; rm -f -- "$job" "%s/initqueue/timeout/resume.sh"; }\n' \
+ "$resume" "$resume" "$hookdir" >> "$hookdir"/initqueue/settled/resume.sh
+
+ {
+ printf -- "%s" 'warn "Cancelling resume operation. Device not found.";'
+ # shellcheck disable=SC2016
+ printf -- ' cancel_wait_for_dev /dev/resume; rm -f -- "$job" "%s/initqueue/settled/resume.sh";\n' "$hookdir"
+ } >> "$hookdir"/initqueue/timeout/resume.sh
+
+ mv /lib/dracut/resume.sh /lib/dracut/hooks/pre-mount/10-resume.sh
+ else
+ {
+ if [ -x /usr/sbin/resume ]; then
+ printf -- '%s' 'SUBSYSTEM=="block", ACTION=="add|change", ENV{ID_FS_TYPE}=="suspend|swsuspend|swsupend",'
+ # shellcheck disable=SC2016
+ printf -- ' RUN+="/sbin/initqueue --finished --unique --name 00resume /usr/sbin/resume %s $tempnode"\n' "$a_splash"
+ fi
+ printf -- '%s' 'SUBSYSTEM=="block", ACTION=="add|change", ENV{ID_FS_TYPE}=="suspend|swsuspend|swsupend",'
+ printf -- '%s\n' ' RUN+="/sbin/initqueue --finished --unique --name 00resume echo %M:%m > /sys/power/resume"'
+ } >> /etc/udev/rules.d/99-resume.rules
+ fi
+fi
diff --git a/modules.d/95resume/resume.sh b/modules.d/95resume/resume.sh
new file mode 100755
index 0000000..c808880
--- /dev/null
+++ b/modules.d/95resume/resume.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+PATH=/usr/sbin:/usr/bin:/sbin:/bin
+
+[ -s /.resume -a -b "$resume" ] && {
+ # First try user level resume; it offers splash etc
+ case "$splash" in
+ quiet)
+ a_splash="-P splash=y"
+ ;;
+ *)
+ a_splash="-P splash=n"
+ ;;
+ esac
+ [ -x "$(command -v resume)" ] && command resume "$a_splash" "$resume"
+
+ (readlink -fn "$resume" > /sys/power/resume) > /.resume
+}
diff --git a/modules.d/95rootfs-block/block-genrules.sh b/modules.d/95rootfs-block/block-genrules.sh
new file mode 100755
index 0000000..d5df0ee
--- /dev/null
+++ b/modules.d/95rootfs-block/block-genrules.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+if [ "${root%%:*}" = "block" ]; then
+ {
+ printf 'KERNEL=="%s", SYMLINK+="root"\n' \
+ "${root#block:/dev/}"
+ printf 'SYMLINK=="%s", SYMLINK+="root"\n' \
+ "${root#block:/dev/}"
+ } >> /etc/udev/rules.d/99-root.rules
+
+ # shellcheck disable=SC2016
+ printf '[ -e "%s" ] && { ln -s "%s" /dev/root 2>/dev/null; rm "$job"; }\n' \
+ "${root#block:}" "${root#block:}" > "$hookdir"/initqueue/settled/blocksymlink.sh
+
+ wait_for_dev "${root#block:}"
+fi
diff --git a/modules.d/95rootfs-block/module-setup.sh b/modules.d/95rootfs-block/module-setup.sh
new file mode 100755
index 0000000..396fb11
--- /dev/null
+++ b/modules.d/95rootfs-block/module-setup.sh
@@ -0,0 +1,92 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ return 0
+}
+
+# called by dracut
+depends() {
+ echo base fs-lib
+}
+
+cmdline_journal() {
+ if [[ $hostonly ]]; then
+ for dev in "${!host_fs_types[@]}"; do
+ [[ ${host_fs_types[$dev]} == "reiserfs" ]] || [[ ${host_fs_types[$dev]} == "xfs" ]] || continue
+ rootopts=$(find_dev_fsopts "$dev")
+ if [[ ${host_fs_types[$dev]} == "reiserfs" ]]; then
+ journaldev=$(fs_get_option "$rootopts" "jdev")
+ elif [[ ${host_fs_types[$dev]} == "xfs" ]]; then
+ journaldev=$(fs_get_option "$rootopts" "logdev")
+ fi
+
+ if [ -n "$journaldev" ]; then
+ printf " root.journaldev=%s" "$journaldev"
+ fi
+ done
+ fi
+ return 0
+}
+
+cmdline_rootfs() {
+ local _block
+ _block=$(find_root_block_device)
+ local _dev=/dev/block/$_block
+ local _fstype _flags _subvol
+
+ # "--no-hostonly-default-device" can result in empty root_devs
+ if [ "${#root_devs[@]}" -eq 0 ]; then
+ return
+ fi
+
+ if [ -n "$_block" -a -b "$_dev" ]; then
+ printf " root=%s" "$(shorten_persistent_dev "$(get_persistent_dev "$_dev")")"
+ fi
+ _fstype="$(find_mp_fstype /)"
+ if [[ ${_fstype} == "zfs" ]]; then
+ local _root_ds
+ _root_ds="$(findmnt -n -o SOURCE /)"
+ printf " root=zfs:%s" "${_root_ds// /+}"
+ fi
+ _flags="$(find_mp_fsopts /)"
+ if [ -n "$_fstype" ]; then
+ printf " rootfstype=%s" "$_fstype"
+ fi
+ if [[ $use_fstab != yes ]] && [[ $_fstype == btrfs ]]; then
+ _subvol=$(findmnt -e -v -n -o FSROOT --target /) \
+ && _subvol=${_subvol#/}
+ _flags="$_flags${_subvol:+,subvol=$_subvol}"
+ fi
+ if [ -n "$_flags" ]; then
+ printf " rootflags=%s" "$_flags"
+ fi
+}
+
+# called by dracut
+cmdline() {
+ cmdline_rootfs
+ cmdline_journal
+}
+
+# called by dracut
+install() {
+ if [[ $hostonly_cmdline == "yes" ]]; then
+ local _journaldev
+ _journaldev=$(cmdline_journal)
+ [[ $_journaldev ]] && printf "%s\n" "$_journaldev" >> "${initdir}/etc/cmdline.d/95root-journaldev.conf"
+ local _rootdev
+ _rootdev=$(cmdline_rootfs)
+ [[ $_rootdev ]] && printf "%s\n" "$_rootdev" >> "${initdir}/etc/cmdline.d/95root-dev.conf"
+ fi
+
+ inst_multiple umount
+ inst_multiple tr
+ if ! dracut_module_included "systemd"; then
+ inst_hook cmdline 95 "$moddir/parse-block.sh"
+ inst_hook pre-udev 30 "$moddir/block-genrules.sh"
+ inst_hook mount 99 "$moddir/mount-root.sh"
+ fi
+
+ inst_hook initqueue/timeout 99 "$moddir/rootfallback.sh"
+}
diff --git a/modules.d/95rootfs-block/mount-root.sh b/modules.d/95rootfs-block/mount-root.sh
new file mode 100755
index 0000000..c488b11
--- /dev/null
+++ b/modules.d/95rootfs-block/mount-root.sh
@@ -0,0 +1,135 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+type det_fs > /dev/null 2>&1 || . /lib/fs-lib.sh
+
+mount_root() {
+ local _rflags_ro
+ # sanity - determine/fix fstype
+ rootfs=$(det_fs "${root#block:}" "$fstype")
+
+ journaldev=$(getarg "root.journaldev=")
+ if [ -n "$journaldev" ]; then
+ case "$rootfs" in
+ xfs)
+ rflags="${rflags:+${rflags},}logdev=$journaldev"
+ ;;
+ reiserfs)
+ fsckoptions="-j $journaldev $fsckoptions"
+ rflags="${rflags:+${rflags},}jdev=$journaldev"
+ ;;
+ *) ;;
+ esac
+ fi
+
+ _rflags_ro="$rflags,ro"
+ _rflags_ro="${_rflags_ro##,}"
+
+ while ! mount -t "${rootfs}" -o "$_rflags_ro" "${root#block:}" "$NEWROOT"; do
+ warn "Failed to mount -t ${rootfs} -o $_rflags_ro ${root#block:} $NEWROOT"
+ fsck_ask_err
+ done
+
+ READONLY=
+ fsckoptions=
+ if [ -f "$NEWROOT"/etc/sysconfig/readonly-root ]; then
+ # shellcheck disable=SC1090
+ . "$NEWROOT"/etc/sysconfig/readonly-root
+ fi
+
+ if getargbool 0 "readonlyroot=" -y readonlyroot; then
+ READONLY=yes
+ fi
+
+ if getarg noreadonlyroot; then
+ READONLY=no
+ fi
+
+ if [ -f "$NEWROOT"/fastboot ] || getargbool 0 fastboot; then
+ fastboot=yes
+ fi
+
+ if ! getargbool 0 rd.skipfsck; then
+ if [ -f "$NEWROOT"/fsckoptions ]; then
+ read -r fsckoptions < "$NEWROOT"/fsckoptions
+ fi
+
+ if [ -f "$NEWROOT"/forcefsck ] || getargbool 0 forcefsck; then
+ fsckoptions="-f $fsckoptions"
+ elif [ -f "$NEWROOT"/.autofsck ]; then
+ # shellcheck disable=SC1090
+ [ -f "$NEWROOT"/etc/sysconfig/autofsck ] \
+ && . "$NEWROOT"/etc/sysconfig/autofsck
+ if [ "$AUTOFSCK_DEF_CHECK" = "yes" ]; then
+ AUTOFSCK_OPT="$AUTOFSCK_OPT -f"
+ fi
+ if [ -n "$AUTOFSCK_SINGLEUSER" ]; then
+ warn "*** Warning -- the system did not shut down cleanly. "
+ warn "*** Dropping you to a shell; the system will continue"
+ warn "*** when you leave the shell."
+ emergency_shell
+ fi
+ fsckoptions="$AUTOFSCK_OPT $fsckoptions"
+ fi
+ fi
+
+ rootopts=
+ if getargbool 1 rd.fstab -d -n rd_NO_FSTAB \
+ && ! getarg rootflags > /dev/null \
+ && [ -f "$NEWROOT/etc/fstab" ] \
+ && ! [ -L "$NEWROOT/etc/fstab" ]; then
+ # if $NEWROOT/etc/fstab contains special mount options for
+ # the root filesystem,
+ # remount it with the proper options
+ rootopts="defaults"
+ while read -r dev mp fs opts _ fsck || [ -n "$dev" ]; do
+ # skip comments
+ [ "${dev%%#*}" != "$dev" ] && continue
+
+ if [ "$mp" = "/" ]; then
+ # sanity - determine/fix fstype
+ rootfs=$(det_fs "${root#block:}" "$fs")
+ rootopts=$opts
+ rootfsck=$fsck
+ break
+ fi
+ done < "$NEWROOT/etc/fstab"
+ fi
+
+ # we want rootflags (rflags) to take precedence so prepend rootopts to
+ # them
+ rflags="${rootopts},${rflags}"
+ rflags="${rflags#,}"
+ rflags="${rflags%,}"
+
+ # backslashes are treated as escape character in fstab
+ # esc_root=$(echo ${root#block:} | sed 's,\\,\\\\,g')
+ # printf '%s %s %s %s 1 1 \n' "$esc_root" "$NEWROOT" "$rootfs" "$rflags" >/etc/fstab
+
+ if fsck_able "$rootfs" \
+ && [ "$rootfsck" != "0" -a -z "$fastboot" -a "$READONLY" != "yes" ] \
+ && ! strstr "${rflags}" _netdev \
+ && ! getargbool 0 rd.skipfsck; then
+ umount "$NEWROOT"
+ fsck_single "${root#block:}" "$rootfs" "$rflags" "$fsckoptions"
+ fi
+
+ echo "${root#block:} $NEWROOT $rootfs ${rflags:-defaults} 0 ${rootfsck:-0}" >> /etc/fstab
+
+ if ! ismounted "$NEWROOT"; then
+ info "Mounting ${root#block:} with -o ${rflags}"
+ mount "$NEWROOT" 2>&1 | vinfo
+ elif ! are_lists_eq , "$rflags" "$_rflags_ro" defaults; then
+ info "Remounting ${root#block:} with -o ${rflags}"
+ mount -o remount "$NEWROOT" 2>&1 | vinfo
+ fi
+
+ if ! getargbool 0 rd.skipfsck; then
+ [ -f "$NEWROOT"/forcefsck ] && rm -f -- "$NEWROOT"/forcefsck 2> /dev/null
+ [ -f "$NEWROOT"/.autofsck ] && rm -f -- "$NEWROOT"/.autofsck 2> /dev/null
+ fi
+}
+
+if [ -n "$root" -a -z "${root%%block:*}" ]; then
+ mount_root
+fi
diff --git a/modules.d/95rootfs-block/parse-block.sh b/modules.d/95rootfs-block/parse-block.sh
new file mode 100755
index 0000000..9c4357e
--- /dev/null
+++ b/modules.d/95rootfs-block/parse-block.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+case "${root#block:}" in
+ LABEL=* | UUID=* | PARTUUID=* | PARTLABEL=*)
+ root="block:$(label_uuid_to_dev "$root")"
+ rootok=1
+ ;;
+ /dev/*)
+ root="block:${root#block:}"
+ # shellcheck disable=SC2034
+ rootok=1
+ ;;
+esac
+
+[ "${root%%:*}" = "block" ] && wait_for_dev "${root#block:}"
diff --git a/modules.d/95rootfs-block/rootfallback.sh b/modules.d/95rootfs-block/rootfallback.sh
new file mode 100755
index 0000000..ce4ee85
--- /dev/null
+++ b/modules.d/95rootfs-block/rootfallback.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+for root in $(getargs rootfallback=); do
+ root=$(label_uuid_to_dev "$root")
+
+ if ! [ -b "$root" ]; then
+ warn "Could not find rootfallback $root"
+ continue
+ fi
+
+ if mount "$root" /sysroot; then
+ info "Mounted rootfallback $root"
+ exit 0
+ else
+ warn "Failed to mount rootfallback $root"
+ exit 1
+ fi
+done
+
+[ -e "$job" ] && rm -f "$job"
diff --git a/modules.d/95ssh-client/module-setup.sh b/modules.d/95ssh-client/module-setup.sh
new file mode 100755
index 0000000..75fc94f
--- /dev/null
+++ b/modules.d/95ssh-client/module-setup.sh
@@ -0,0 +1,80 @@
+#!/bin/bash
+
+# fixme: assume user is root
+
+# called by dracut
+check() {
+ [[ $mount_needs ]] && return 1
+
+ # If our prerequisites are not met, fail.
+ require_binaries ssh scp || return 1
+
+ if [[ $sshkey ]]; then
+ [[ ! -f $dracutsysrootdir$sshkey ]] && {
+ derror "ssh key: $sshkey is not found!"
+ return 1
+ }
+ fi
+
+ return 255
+}
+
+# called by dracut
+depends() {
+ # We depend on network modules being loaded
+ echo network
+}
+
+inst_sshenv() {
+ if [[ -d $dracutsysrootdir/root/.ssh ]]; then
+ inst_dir /root/.ssh
+ chmod 700 "${initdir}"/root/.ssh
+ fi
+
+ # Copy over ssh key and knowhosts if needed
+ [[ $sshkey ]] && {
+ inst_simple "$sshkey"
+ [[ -f $dracutsysrootdir/root/.ssh/known_hosts ]] && inst_simple /root/.ssh/known_hosts
+ [[ -f $dracutsysrootdir/etc/ssh/ssh_known_hosts ]] && inst_simple /etc/ssh/ssh_known_hosts
+ }
+
+ # Copy over root and system-wide ssh configs.
+ [[ -f $dracutsysrootdir/root/.ssh/config ]] && inst_simple /root/.ssh/config
+ if [[ -f $dracutsysrootdir/etc/ssh/ssh_config ]]; then
+ inst_simple /etc/ssh/ssh_config
+ sed -i -e 's/\(^[[:space:]]*\)ProxyCommand/\1# ProxyCommand/' "${initdir}"/etc/ssh/ssh_config
+ while read -r key val || [ -n "$key" ]; do
+ if [[ $key == "GlobalKnownHostsFile" ]]; then
+ inst_simple "$val"
+ # Copy customized UserKnowHostsFile
+ elif [[ $key == "UserKnownHostsFile" ]]; then
+ # Make sure that ~/foo will be copied as /root/foo in kdump's initramfs
+ # shellcheck disable=SC2088
+ if str_starts "$val" "~/"; then
+ val="/root/${val#"~/"}"
+ fi
+ inst_simple "$val"
+ fi
+ done < "$dracutsysrootdir"/etc/ssh/ssh_config
+ fi
+
+ return 0
+}
+
+# called by dracut
+install() {
+ local _nsslibs
+
+ inst_multiple ssh scp
+ inst_sshenv
+
+ _nsslibs=$(
+ cat "$dracutsysrootdir"/{,usr/}etc/nsswitch.conf 2> /dev/null \
+ | sed -e 's/#.*//; s/^[^:]*://; s/\[[^]]*\]//' \
+ | tr -s '[:space:]' '\n' | sort -u | tr -s '[:space:]' '|'
+ )
+ _nsslibs=${_nsslibs#|}
+ _nsslibs=${_nsslibs%|}
+
+ inst_libdir_file -n "$_nsslibs" 'libnss_*.so*'
+}
diff --git a/modules.d/95terminfo/module-setup.sh b/modules.d/95terminfo/module-setup.sh
new file mode 100755
index 0000000..8cecaf3
--- /dev/null
+++ b/modules.d/95terminfo/module-setup.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+# called by dracut
+install() {
+ local _terminfodir
+ # terminfo bits make things work better if you fall into interactive mode
+ for _terminfodir in /lib/terminfo /etc/terminfo /usr/share/terminfo; do
+ [[ -f $dracutsysrootdir${_terminfodir}/l/linux ]] && break
+ done
+
+ if [[ -d $dracutsysrootdir${_terminfodir} ]]; then
+ for i in "l/linux" "v/vt100" "v/vt102" "v/vt220"; do
+ inst_dir "$_terminfodir/${i%/*}"
+ $DRACUT_CP -L -t "${initdir}/${_terminfodir}/${i%/*}" "$dracutsysrootdir$_terminfodir/$i"
+ done
+ fi
+}
diff --git a/modules.d/95udev-rules/59-persistent-storage.rules b/modules.d/95udev-rules/59-persistent-storage.rules
new file mode 100644
index 0000000..b076937
--- /dev/null
+++ b/modules.d/95udev-rules/59-persistent-storage.rules
@@ -0,0 +1,9 @@
+SUBSYSTEM!="block", GOTO="ps_end"
+ACTION!="add|change", GOTO="ps_end"
+# Also don't process disks that are slated to be a multipath device
+ENV{DM_MULTIPATH_DEVICE_PATH}=="1", GOTO="ps_end"
+
+KERNEL=="cciss[0-9]*", IMPORT{builtin}="blkid"
+KERNEL=="nbd[0-9]*", IMPORT{builtin}="blkid"
+
+LABEL="ps_end"
diff --git a/modules.d/95udev-rules/61-persistent-storage.rules b/modules.d/95udev-rules/61-persistent-storage.rules
new file mode 100644
index 0000000..053b65c
--- /dev/null
+++ b/modules.d/95udev-rules/61-persistent-storage.rules
@@ -0,0 +1,22 @@
+SUBSYSTEM!="block", GOTO="pss_end"
+ACTION!="add|change", GOTO="pss_end"
+# Also don't process disks that are slated to be a multipath device
+ENV{DM_MULTIPATH_DEVICE_PATH}=="1", GOTO="pss_end"
+
+ACTION=="change", KERNEL=="dm-[0-9]*", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}!="1", GOTO="do_pss"
+KERNEL=="cciss[0-9]*", GOTO="do_pss"
+KERNEL=="nbd[0-9]*", GOTO="do_pss"
+KERNEL=="md[0-9]*|md_d[0-9]*|md/*", GOTO="do_pss"
+
+GOTO="pss_end"
+
+LABEL="do_pss"
+# by-path (parent device path)
+ENV{DEVTYPE}=="disk", ENV{ID_PATH}=="", DEVPATH!="*/virtual/*", IMPORT{builtin}="path_id"
+ENV{DEVTYPE}=="disk", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}"
+ENV{DEVTYPE}=="partition", ENV{ID_PATH}=="?*", SYMLINK+="disk/by-path/$env{ID_PATH}-part%n"
+
+# by-label/by-uuid links (filesystem metadata)
+ENV{ID_FS_USAGE}=="filesystem|other|crypto", ENV{ID_FS_UUID_ENC}=="?*", SYMLINK+="disk/by-uuid/$env{ID_FS_UUID_ENC}"
+ENV{ID_FS_USAGE}=="filesystem|other", ENV{ID_FS_LABEL_ENC}=="?*", SYMLINK+="disk/by-label/$env{ID_FS_LABEL_ENC}"
+LABEL="pss_end"
diff --git a/modules.d/95udev-rules/module-setup.sh b/modules.d/95udev-rules/module-setup.sh
new file mode 100755
index 0000000..3ca12ee
--- /dev/null
+++ b/modules.d/95udev-rules/module-setup.sh
@@ -0,0 +1,83 @@
+#!/bin/bash
+
+# called by dracut
+install() {
+ local _i
+
+ # Fixme: would be nice if we didn't have to guess, which rules to grab....
+ # ultimately, /lib/initramfs/rules.d or somesuch which includes links/copies
+ # of the rules we want so that we just copy those in would be best
+ inst_multiple udevadm cat uname blkid
+ inst_dir /etc/udev
+ inst_multiple -o /etc/udev/udev.conf
+
+ [[ -d ${initdir}/$systemdutildir ]] || mkdir -p "${initdir}/$systemdutildir"
+ for _i in "${systemdutildir}"/systemd-udevd "${udevdir}"/udevd /sbin/udevd; do
+ [[ -x $dracutsysrootdir$_i ]] || continue
+ inst "$_i"
+
+ if ! [[ -f ${initdir}${systemdutildir}/systemd-udevd ]]; then
+ ln -fs "$_i" "${initdir}${systemdutildir}"/systemd-udevd
+ fi
+ break
+ done
+ if ! [[ -e ${initdir}${systemdutildir}/systemd-udevd ]]; then
+ derror "Cannot find [systemd-]udevd binary!"
+ exit 1
+ fi
+
+ inst_rules \
+ 50-udev-default.rules \
+ 55-scsi-sg3_id.rules \
+ 58-scsi-sg3_symlink.rules \
+ 59-scsi-sg3_utils.rules \
+ 60-block.rules \
+ 60-cdrom_id.rules \
+ 60-pcmcia.rules \
+ 60-persistent-storage.rules \
+ 64-btrfs.rules \
+ 70-uaccess.rules \
+ 71-seat.rules \
+ 73-seat-late.rules \
+ 75-net-description.rules \
+ 80-drivers.rules 95-udev-late.rules \
+ 80-net-name-slot.rules 80-net-setup-link.rules \
+ "$moddir/59-persistent-storage.rules" \
+ "$moddir/61-persistent-storage.rules"
+
+ # legacy persistent network device name rules
+ [[ $hostonly ]] && inst_rules 70-persistent-net.rules
+
+ {
+ for i in cdrom tape dialout floppy; do
+ if ! grep -q "^$i:" "$initdir"/etc/group 2> /dev/null; then
+ if ! grep "^$i:" "$dracutsysrootdir"/etc/group 2> /dev/null; then
+ case $i in
+ cdrom) echo "$i:x:11:" ;;
+ dialout) echo "$i:x:18:" ;;
+ floppy) echo "$i:x:19:" ;;
+ tape) echo "$i:x:33:" ;;
+ esac
+ fi
+ fi
+ done
+ } >> "$initdir/etc/group"
+
+ inst_multiple -o \
+ "${udevdir}"/ata_id \
+ "${udevdir}"/cdrom_id \
+ "${udevdir}"/create_floppy_devices \
+ "${udevdir}"/fw_unit_symlinks.sh \
+ "${udevdir}"/hid2hci \
+ "${udevdir}"/path_id \
+ "${udevdir}"/input_id \
+ "${udevdir}"/scsi_id \
+ "${udevdir}"/usb_id \
+ "${udevdir}"/pcmcia-socket-startup \
+ "${udevdir}"/pcmcia-check-broken-cis
+
+ inst_multiple -o /etc/pcmcia/config.opts
+
+ inst_libdir_file "libnss_files*"
+
+}
diff --git a/modules.d/95virtfs/module-setup.sh b/modules.d/95virtfs/module-setup.sh
new file mode 100755
index 0000000..8026002
--- /dev/null
+++ b/modules.d/95virtfs/module-setup.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ [[ $hostonly ]] || [[ $mount_needs ]] && {
+ for fs in "${host_fs_types[@]}"; do
+ [[ $fs == "9p" ]] && return 0
+ done
+ return 255
+ }
+
+ is_qemu_virtualized && return 0
+
+ return 255
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ instmods 9p 9pnet_virtio virtio_pci
+}
+
+# called by dracut
+install() {
+ inst_hook cmdline 95 "$moddir/parse-virtfs.sh"
+ inst_hook mount 99 "$moddir/mount-virtfs.sh"
+}
diff --git a/modules.d/95virtfs/mount-virtfs.sh b/modules.d/95virtfs/mount-virtfs.sh
new file mode 100755
index 0000000..e52c752
--- /dev/null
+++ b/modules.d/95virtfs/mount-virtfs.sh
@@ -0,0 +1,74 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+filter_rootopts() {
+ rootopts=$1
+ # strip ro and rw options
+ local OLDIFS="$IFS"
+ IFS=,
+ # shellcheck disable=SC2086
+ set -- $rootopts
+ IFS="$OLDIFS"
+ local v
+ while [ $# -gt 0 ]; do
+ case $1 in
+ rw | ro) ;;
+ defaults) ;;
+ *)
+ v="$v,${1}"
+ ;;
+ esac
+ shift
+ done
+ rootopts=${v#,}
+ echo "$rootopts"
+}
+
+mount_root() {
+ rootfs="9p"
+ rflags="trans=virtio,version=9p2000.L"
+
+ modprobe 9pnet_virtio
+
+ mount -t ${rootfs} -o "$rflags",ro "${root#virtfs:}" "$NEWROOT"
+
+ rootopts=
+ if getargbool 1 rd.fstab -n rd_NO_FSTAB \
+ && ! getarg rootflags \
+ && [ -f "$NEWROOT/etc/fstab" ] \
+ && ! [ -L "$NEWROOT/etc/fstab" ]; then
+ # if $NEWROOT/etc/fstab contains special mount options for
+ # the root filesystem,
+ # remount it with the proper options
+ rootopts="defaults"
+ while read -r dev mp _ opts rest || [ -n "$dev" ]; do
+ # skip comments
+ [ "${dev%%#*}" != "$dev" ] && continue
+
+ if [ "$mp" = "/" ]; then
+ rootopts=$opts
+ break
+ fi
+ done < "$NEWROOT/etc/fstab"
+
+ rootopts=$(filter_rootopts "$rootopts")
+ fi
+
+ # we want rootflags (rflags) to take precedence so prepend rootopts to
+ # them; rflags is guaranteed to not be empty
+ rflags="${rootopts:+${rootopts},}${rflags}"
+
+ umount "$NEWROOT"
+
+ info "Remounting ${root#virtfs:} with -o ${rflags}"
+ mount -t ${rootfs} -o "$rflags" "${root#virtfs:}" "$NEWROOT" 2>&1 | vinfo
+
+ [ -f "$NEWROOT"/forcefsck ] && rm -f -- "$NEWROOT"/forcefsck 2> /dev/null
+ [ -f "$NEWROOT"/.autofsck ] && rm -f -- "$NEWROOT"/.autofsck 2> /dev/null
+}
+
+if [ -n "$root" -a -z "${root%%virtfs:*}" ]; then
+ mount_root
+fi
+:
diff --git a/modules.d/95virtfs/parse-virtfs.sh b/modules.d/95virtfs/parse-virtfs.sh
new file mode 100755
index 0000000..9f67123
--- /dev/null
+++ b/modules.d/95virtfs/parse-virtfs.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+if [ "${root%%:*}" = "virtfs" ]; then
+ modprobe 9pnet_virtio
+
+ # shellcheck disable=SC2034
+ rootok=1
+fi
diff --git a/modules.d/95virtiofs/module-setup.sh b/modules.d/95virtiofs/module-setup.sh
new file mode 100755
index 0000000..176482b
--- /dev/null
+++ b/modules.d/95virtiofs/module-setup.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ [[ $hostonly ]] || [[ $mount_needs ]] && {
+ is_qemu_virtualized && return 0
+
+ for fs in "${host_fs_types[@]}"; do
+ [[ $fs == "virtiofs" ]] && return 0
+ done
+ return 255
+ }
+
+ return 0
+}
+
+# called by dracut
+depends() {
+ echo base
+}
+
+# called by dracut
+installkernel() {
+ instmods virtiofs virtio_pci
+}
+
+# called by dracut
+install() {
+ inst_hook cmdline 95 "$moddir/parse-virtiofs.sh"
+ inst_hook pre-mount 99 "$moddir/mount-virtiofs.sh"
+}
diff --git a/modules.d/95virtiofs/mount-virtiofs.sh b/modules.d/95virtiofs/mount-virtiofs.sh
new file mode 100755
index 0000000..3d73884
--- /dev/null
+++ b/modules.d/95virtiofs/mount-virtiofs.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+type ismounted > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+if [ "${fstype}" = "virtiofs" -o "${root%%:*}" = "virtiofs" ]; then
+ if ! load_fstype virtiofs; then
+ die "virtiofs is required but not available."
+ fi
+
+ mount -t virtiofs -o "$rflags" "${root#virtiofs:}" "$NEWROOT" 2>&1 | vinfo
+ if ! ismounted "$NEWROOT"; then
+ die "virtiofs: failed to mount root fs"
+ fi
+
+ info "virtiofs: root fs mounted (options: '${rflags}')"
+
+ [ -f "$NEWROOT"/forcefsck ] && rm -f -- "$NEWROOT"/forcefsck 2> /dev/null
+ [ -f "$NEWROOT"/.autofsck ] && rm -f -- "$NEWROOT"/.autofsck 2> /dev/null
+fi
+:
diff --git a/modules.d/95virtiofs/parse-virtiofs.sh b/modules.d/95virtiofs/parse-virtiofs.sh
new file mode 100755
index 0000000..760e413
--- /dev/null
+++ b/modules.d/95virtiofs/parse-virtiofs.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+# Accepted formats:
+# rootfstype=virtiofs root=<tag>
+# root=virtiofs:<tag>
+
+if [ "${fstype}" = "virtiofs" -o "${root%%:*}" = "virtiofs" ]; then
+ # shellcheck disable=SC2034
+ rootok=1
+fi
diff --git a/modules.d/95zfcp/module-setup.sh b/modules.d/95zfcp/module-setup.sh
new file mode 100755
index 0000000..e1f3aa3
--- /dev/null
+++ b/modules.d/95zfcp/module-setup.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ arch=${DRACUT_ARCH:-$(uname -m)}
+ [ "$arch" = "s390" -o "$arch" = "s390x" ] || return 1
+
+ require_binaries zfcp_cio_free grep sed seq || return 1
+
+ return 0
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ instmods zfcp
+}
+
+# called by dracut
+install() {
+ inst_hook cmdline 30 "$moddir/parse-zfcp.sh"
+ inst_multiple zfcp_cio_free grep sed seq
+
+ inst_script /sbin/zfcpconf.sh
+ inst_rules 56-zfcp.rules
+
+ if [[ $hostonly ]]; then
+ inst_simple -H /etc/zfcp.conf
+ fi
+}
diff --git a/modules.d/95zfcp/parse-zfcp.sh b/modules.d/95zfcp/parse-zfcp.sh
new file mode 100755
index 0000000..495aa67
--- /dev/null
+++ b/modules.d/95zfcp/parse-zfcp.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+getargbool 1 rd.zfcp.conf -d -n rd_NO_ZFCPCONF || rm /etc/zfcp.conf
+
+for zfcp_arg in $(getargs rd.zfcp -d 'rd_ZFCP='); do
+ echo "$zfcp_arg" | grep '^0\.[0-9a-fA-F]\.[0-9a-fA-F]\{4\}\(,0x[0-9a-fA-F]\{16\},0x[0-9a-fA-F]\{16\}\)\?$' > /dev/null
+ test $? -ne 0 && die "For argument 'rd.zfcp=$zfcp_arg'\nSorry, invalid format."
+ (
+ IFS=","
+ # shellcheck disable=SC2086
+ set $zfcp_arg
+ echo "$@" >> /etc/zfcp.conf
+ )
+done
+
+zfcp_cio_free
diff --git a/modules.d/95zfcp_rules/module-setup.sh b/modules.d/95zfcp_rules/module-setup.sh
new file mode 100755
index 0000000..dfa7951
--- /dev/null
+++ b/modules.d/95zfcp_rules/module-setup.sh
@@ -0,0 +1,80 @@
+#!/bin/bash
+
+# called by dracut
+cmdline() {
+ is_zfcp() {
+ local _dev=$1
+ local _devpath
+ _devpath=$(
+ cd -P /sys/dev/block/"$_dev" || exit
+ echo "$PWD"
+ )
+ local _sdev _scsiid _hostno _lun _wwpn _ccw _port_type
+ local _allow_lun_scan _is_npiv
+
+ read -r _allow_lun_scan < /sys/module/zfcp/parameters/allow_lun_scan
+ [ "${_devpath#*/sd}" == "$_devpath" ] && return 1
+ _sdev="${_devpath%%/block/*}"
+ [ -e "${_sdev}"/fcp_lun ] || return 1
+ _scsiid="${_sdev##*/}"
+ _hostno="${_scsiid%%:*}"
+ [ -d /sys/class/fc_host/host"${_hostno}" ] || return 1
+ read -r _port_type < /sys/class/fc_host/host"${_hostno}"/port_type
+ case "$_port_type" in
+ NPIV*)
+ _is_npiv=1
+ ;;
+ esac
+ read -r _ccw < "${_sdev}"/hba_id
+ if [ "$_is_npiv" ] && [ "$_allow_lun_scan" = "Y" ]; then
+ echo "rd.zfcp=${_ccw}"
+ else
+ read -r _lun < "${_sdev}"/fcp_lun
+ read -r _wwpn < "${_sdev}"/wwpn
+ echo "rd.zfcp=${_ccw},${_wwpn},${_lun}"
+ fi
+ return 0
+ }
+ [[ $hostonly ]] || [[ $mount_needs ]] && {
+ for_each_host_dev_and_slaves_all is_zfcp
+ } | sort | uniq
+}
+
+# called by dracut
+check() {
+ local _arch=${DRACUT_ARCH:-$(uname -m)}
+ local _ccw
+ [ "$_arch" = "s390" -o "$_arch" = "s390x" ] || return 1
+
+ [[ $hostonly ]] || [[ $mount_needs ]] && {
+ found=0
+ for _ccw in /sys/bus/ccw/devices/*/host*; do
+ [ -d "$_ccw" ] || continue
+ found=$((found + 1))
+ done
+ [ $found -eq 0 ] && return 255
+ }
+ return 0
+}
+
+# called by dracut
+depends() {
+ echo bash
+ return 0
+}
+
+# called by dracut
+install() {
+ inst_hook cmdline 30 "$moddir/parse-zfcp.sh"
+ if [[ $hostonly_cmdline == "yes" ]]; then
+ local _zfcp
+
+ for _zfcp in $(cmdline); do
+ printf "%s\n" "$_zfcp" >> "${initdir}/etc/cmdline.d/94zfcp.conf"
+ done
+ fi
+ if [[ $hostonly ]]; then
+ inst_rules_wildcard "51-zfcp-*.rules"
+ inst_rules_wildcard "41-zfcp-*.rules"
+ fi
+}
diff --git a/modules.d/95zfcp_rules/parse-zfcp.sh b/modules.d/95zfcp_rules/parse-zfcp.sh
new file mode 100755
index 0000000..5e7d909
--- /dev/null
+++ b/modules.d/95zfcp_rules/parse-zfcp.sh
@@ -0,0 +1,73 @@
+#!/bin/bash
+
+create_udev_rule() {
+ local ccw=$1
+ local wwpn=$2
+ local lun=$3
+ local _rule=/etc/udev/rules.d/51-zfcp-${ccw}.rules
+ local _cu_type _dev_type
+
+ if [ -x /sbin/cio_ignore ] && cio_ignore -i "$ccw" > /dev/null; then
+ cio_ignore -r "$ccw"
+ fi
+
+ if [ -e /sys/bus/ccw/devices/"${ccw}" ]; then
+ read -r _cu_type < /sys/bus/ccw/devices/"${ccw}"/cutype
+ read -r _dev_type < /sys/bus/ccw/devices/"${ccw}"/devtype
+ fi
+ if [ "$_cu_type" != "1731/03" ]; then
+ return 0
+ fi
+ if [ "$_dev_type" != "1732/03" ] && [ "$_dev_type" != "1732/04" ]; then
+ return 0
+ fi
+
+ [ -z "$wwpn" ] || [ -z "$lun" ] && return
+ m=$(sed -n "/.*${wwpn}.*${lun}.*/p" "$_rule")
+ if [ -z "$m" ]; then
+ cat >> "$_rule" << EOF
+ACTION=="add", KERNEL=="rport-*", ATTR{port_name}=="$wwpn", SUBSYSTEMS=="ccw", KERNELS=="$ccw", ATTR{[ccw/$ccw]$wwpn/unit_add}="$lun"
+EOF
+ fi
+}
+
+if [[ -f /sys/firmware/ipl/ipl_type ]] \
+ && [[ $(< /sys/firmware/ipl/ipl_type) == "fcp" ]]; then
+ (
+ read -r _wwpn < /sys/firmware/ipl/wwpn
+ read -r _lun < /sys/firmware/ipl/lun
+ read -r _ccw < /sys/firmware/ipl/device
+
+ create_udev_rule "$_ccw" "$_wwpn" "$_lun"
+ )
+fi
+
+for zfcp_arg in $(getargs rd.zfcp); do
+ (
+ OLDIFS="$IFS"
+ IFS=","
+ # shellcheck disable=SC2086
+ set $zfcp_arg
+ IFS="$OLDIFS"
+ create_udev_rule "$1" "$2" "$3"
+ )
+done
+
+for zfcp_arg in $(getargs root=) $(getargs resume=); do
+ (
+ case $zfcp_arg in
+ /dev/disk/by-path/ccw-*)
+ ccw_arg=${zfcp_arg##*/}
+ ;;
+ esac
+ if [ -n "$ccw_arg" ]; then
+ OLDIFS="$IFS"
+ IFS="-"
+ set -- "$ccw_arg"
+ IFS="$OLDIFS"
+ _wwpn=${4%:*}
+ _lun=${4#*:}
+ create_udev_rule "$2" "$wwpn" "$lun"
+ fi
+ )
+done
diff --git a/modules.d/95znet/module-setup.sh b/modules.d/95znet/module-setup.sh
new file mode 100755
index 0000000..df37c66
--- /dev/null
+++ b/modules.d/95znet/module-setup.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ arch=${DRACUT_ARCH:-$(uname -m)}
+ [ "$arch" = "s390" -o "$arch" = "s390x" ] || return 1
+
+ require_binaries znet_cio_free grep sed seq readlink || return 1
+
+ return 0
+}
+
+# called by dracut
+depends() {
+ echo bash
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ instmods ctcm lcs qeth qeth_l2 qeth_l3
+}
+
+# called by dracut
+install() {
+ inst_hook cmdline 30 "$moddir/parse-ccw.sh"
+ inst_rules 81-ccw.rules
+ inst_multiple znet_cio_free grep sed seq readlink /lib/udev/ccw_init
+}
diff --git a/modules.d/95znet/parse-ccw.sh b/modules.d/95znet/parse-ccw.sh
new file mode 100755
index 0000000..d895360
--- /dev/null
+++ b/modules.d/95znet/parse-ccw.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+for ccw_arg in $(getargs rd.ccw -d 'rd_CCW=') $(getargs rd.znet -d 'rd_ZNET='); do
+ echo "$ccw_arg" >> /etc/ccw.conf
+done
+
+for ifname in $(getargs rd.znet_ifname); do
+ IFS=: read -r ifname_if ifname_subchannels _rest <<< "$ifname"
+ if [ -z "$ifname_if" ] || [ -z "$ifname_subchannels" ] || [ -n "$_rest" ]; then
+ warn "Invalid arguments for rd.znet_ifname="
+ else
+ {
+ ifname_subchannels=${ifname_subchannels//,/|}
+
+ echo 'ACTION!="add|change", GOTO="ccw_ifname_end"'
+ echo 'ATTR{type}!="1", GOTO="ccw_ifname_end"'
+ echo 'SUBSYSTEM!="net", GOTO="ccw_ifname_end"'
+ echo "SUBSYSTEMS==\"ccwgroup\", KERNELS==\"$ifname_subchannels\", DRIVERS==\"?*\" NAME=\"$ifname_if\""
+ echo 'LABEL="ccw_ifname_end"'
+
+ } > /etc/udev/rules.d/81-ccw-ifname.rules
+ fi
+done
+
+znet_cio_free
diff --git a/modules.d/96securityfs/module-setup.sh b/modules.d/96securityfs/module-setup.sh
new file mode 100755
index 0000000..1181b71
--- /dev/null
+++ b/modules.d/96securityfs/module-setup.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ return 255
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+# called by dracut
+install() {
+ inst_hook cmdline 60 "$moddir/securityfs.sh"
+}
diff --git a/modules.d/96securityfs/securityfs.sh b/modules.d/96securityfs/securityfs.sh
new file mode 100755
index 0000000..2493c1d
--- /dev/null
+++ b/modules.d/96securityfs/securityfs.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+SECURITYFSDIR="/sys/kernel/security"
+export SECURITYFSDIR
+
+if ! findmnt "${SECURITYFSDIR}" > /dev/null 2>&1; then
+ mount -t securityfs -o nosuid,noexec,nodev securityfs ${SECURITYFSDIR} > /dev/null 2>&1
+fi
diff --git a/modules.d/97biosdevname/module-setup.sh b/modules.d/97biosdevname/module-setup.sh
new file mode 100755
index 0000000..c10200d
--- /dev/null
+++ b/modules.d/97biosdevname/module-setup.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ [[ "$mount_needs" ]] && return 1
+ require_binaries biosdevname || return 1
+ return 0
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+# called by dracut
+install() {
+ inst_multiple biosdevname
+ inst_rules 71-biosdevname.rules
+}
diff --git a/modules.d/97biosdevname/parse-biosdevname.sh b/modules.d/97biosdevname/parse-biosdevname.sh
new file mode 100755
index 0000000..452873f
--- /dev/null
+++ b/modules.d/97biosdevname/parse-biosdevname.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+if ! getargbool 1 biosdevname; then
+ info "biosdevname=0: removing biosdevname network renaming"
+ udevproperty UDEV_BIOSDEVNAME=
+ rm -f -- /etc/udev/rules.d/71-biosdevname.rules
+else
+ info "biosdevname=1: activating biosdevname network renaming"
+ udevproperty UDEV_BIOSDEVNAME=1
+fi
diff --git a/modules.d/97masterkey/README b/modules.d/97masterkey/README
new file mode 100644
index 0000000..524ccfc
--- /dev/null
+++ b/modules.d/97masterkey/README
@@ -0,0 +1,68 @@
+# Directions for creating the kernel master key that will be used for
+# encrypting/decrypting other keys.
+
+# A trusted key is a TPM random number, which is only ever exposed to
+# userspace as an encrypted datablob. A trusted key can be sealed to a
+# set of PCR values. For more details on trusted keys, refer to the
+# kernel keys-trusted-encrypted.txt documentation.
+$ keyctl add trusted kmk-trusted "new 32" @u
+801713097
+
+# For those systems which don't have a TPM, but want to experiment with
+# encrypted keys, create a user key of 32 random bytes. Unlike
+# trusted/encrypted keys, user type key data is visible to userspace.
+$ keyctl add user kmk-user "`dd if=/dev/urandom bs=1 count=32 2>/dev/null`" @u
+144468621
+
+# Save the kernel master key (trusted type):
+$ su -c 'keyctl pipe `keyctl search @u trusted kmk-trusted` > /etc/keys/kmk-trusted.blob'
+
+# or (user type):
+$ su -c 'keyctl pipe `keyctl search @u user kmk-user` > /etc/keys/kmk-user.blob'
+
+# A useful feature of trusted keys is that it is possible to prevent their
+# unsealing at later time by providing the parameter 'pcrlock=<pcrnum>' when
+# loading it, which causes the PCR #<pcrnum> to be extended with a random value.
+# Actually, the <pcrnum> variable is set to '11' to let users experiment with
+# this feature by using a register that is never extended during the boot,
+# making the re-sealing not necessary. In the future, the kernel master key will
+# be sealed to the PCR #14 which is extended, according to the TrustedGRUB
+# documentation[1], to the measure of the kernel and the initial ramdisk.
+
+# The kernel master key path name and type can be set in one of the following
+# ways (specified in the order in which variables are overwritten):
+
+1) use default values:
+--------------------------------------------------------------------------
+MULTIKERNELMODE="NO"
+MASTERKEYTYPE="trusted"
+MASTERKEY="/etc/keys/kmk-${MASTERKEYTYPE}.blob"
+--------------------------------------------------------------------------
+
+2) create the configuration file '/etc/sysconfig/masterkey' to override the
+value of one or all variables;
+
+3) specify these parameters in the kernel command line:
+- masterkey=</kernel/master/key/path>, to override the MASTERKEY variable;
+- masterkeytype=<kernel-master-key-type>, to override the MASTERKEYTYPE variable.
+
+# The variable MULTIKERNELMODE has been introduced to support multi boot
+# configurations, where a trusted/user key is tied to a specific kernel and
+# initial ramdisk. In this case, setting MULTIKERNELMODE to 'YES' will cause the
+# kernel version to be added to the default masterkey path name, so that the
+# MASTERKEY variable should not be overridden each time a different kernel is
+# chosen. The default value of MASTERKEY will be equal to:
+--------------------------------------------------------------------------
+MASTERKEY="/etc/keys/kmk-${MASTERKEYTYPE}-$(uname -r).blob"
+--------------------------------------------------------------------------
+
+# The masterkey path name also depends on the value of MASTERKEYTYPE, as reported
+# in the default values for defined variables. For example, if only MASTERKEYTYPE
+# is overridden by setting it to 'user' in the configuration file or from the
+# kernel command line, the value of MASTERKEY will be:
+--------------------------------------------------------------------------
+MASTERKEY="/etc/keys/kmk-user.blob"
+--------------------------------------------------------------------------
+
+
+[1] https://projects.sirrix.com/trac/trustedgrub/
diff --git a/modules.d/97masterkey/masterkey.sh b/modules.d/97masterkey/masterkey.sh
new file mode 100755
index 0000000..6dd6a4d
--- /dev/null
+++ b/modules.d/97masterkey/masterkey.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+# Licensed under the GPLv2
+#
+# Copyright (C) 2011 Politecnico di Torino, Italy
+# TORSEC group -- http://security.polito.it
+# Roberto Sassu <roberto.sassu@polito.it>
+
+MASTERKEYSCONFIG="${NEWROOT}/etc/sysconfig/masterkey"
+MULTIKERNELMODE="NO"
+PCRLOCKNUM=11
+
+load_masterkey() {
+ # read the configuration from the config file
+ # shellcheck disable=SC1090
+ [ -f "${MASTERKEYSCONFIG}" ] \
+ && . "${MASTERKEYSCONFIG}"
+
+ # override the kernel master key path name from the 'masterkey=' parameter
+ # in the kernel command line
+ MASTERKEYARG=$(getarg masterkey=) && MASTERKEY=${MASTERKEYARG}
+
+ # override the kernel master key type from the 'masterkeytype=' parameter
+ # in the kernel command line
+ MASTERKEYTYPEARG=$(getarg masterkeytype=) && MASTERKEYTYPE=${MASTERKEYTYPEARG}
+
+ # set default values
+ [ -z "${MASTERKEYTYPE}" ] \
+ && MASTERKEYTYPE="trusted"
+
+ if [ -z "${MASTERKEY}" ]; then
+ # append the kernel version to the default masterkey path name
+ # if MULTIKERNELMODE is set to YES
+ if [ "${MULTIKERNELMODE}" = "YES" ]; then
+ MASTERKEY="/etc/keys/kmk-${MASTERKEYTYPE}-$(uname -r).blob"
+ else
+ MASTERKEY="/etc/keys/kmk-${MASTERKEYTYPE}.blob"
+ fi
+ fi
+
+ # set the kernel master key path name
+ MASTERKEYPATH="${NEWROOT}${MASTERKEY}"
+
+ # check for kernel master key's existence
+ if [ ! -f "${MASTERKEYPATH}" ]; then
+ if [ "${RD_DEBUG}" = "yes" ]; then
+ info "masterkey: kernel master key file not found: ${MASTERKEYPATH}"
+ fi
+ return 1
+ fi
+
+ # read the kernel master key blob
+ read -r KEYBLOB < "${MASTERKEYPATH}"
+
+ # add the 'load' prefix if the key type is 'trusted'
+ [ "${MASTERKEYTYPE}" = "trusted" ] \
+ && KEYBLOB="load ${KEYBLOB} pcrlock=${PCRLOCKNUM}"
+
+ # load the kernel master key
+ info "Loading the kernel master key"
+ keyctl add "${MASTERKEYTYPE}" "kmk-${MASTERKEYTYPE}" "${KEYBLOB}" @u > /dev/null || {
+ info "masterkey: failed to load the kernel master key: kmk-${MASTERKEYTYPE}"
+ return 1
+ }
+
+ return 0
+}
+
+load_masterkey
diff --git a/modules.d/97masterkey/module-setup.sh b/modules.d/97masterkey/module-setup.sh
new file mode 100755
index 0000000..49b006e
--- /dev/null
+++ b/modules.d/97masterkey/module-setup.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ [[ $hostonly ]] && {
+ require_binaries keyctl uname || return 1
+ }
+
+ return 255
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ instmods trusted encrypted
+}
+
+# called by dracut
+install() {
+ inst_multiple keyctl uname
+ inst_hook pre-pivot 60 "$moddir/masterkey.sh"
+}
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
diff --git a/modules.d/98ecryptfs/README b/modules.d/98ecryptfs/README
new file mode 100644
index 0000000..f741c54
--- /dev/null
+++ b/modules.d/98ecryptfs/README
@@ -0,0 +1,50 @@
+# Directions for creating the encrypted key that will be used to mount an
+# eCryptfs filesystem
+
+# Create the eCryptfs key (encrypted key type)
+#
+# The encrypted key type supports two formats: the 'default' format allows
+# to generate a random symmetric key of the length specified, the 'ecryptfs'
+# format generates an authentication token for the eCryptfs filesystem,
+# which contains a randomly generated key. Two requirements for the latter
+# format is that the key description must contain exactly 16 hexadecimal
+# characters and that the encrypted key length must be equal to 64.
+$ keyctl add encrypted 1000100010001000 "new ecryptfs trusted:kmk-trusted 64" @u
+782117972
+
+# Save the encrypted key
+$ su -c 'keyctl pipe `keyctl search @u encrypted 1000100010001000` > /etc/keys/ecryptfs-trusted.blob'
+
+# The eCryptfs key path name can be set in one of the following ways (specified in
+# the order in which the variable is overwritten):
+
+1) use the default value:
+--------------------------------------------------------------------------
+ECRYPTFSKEY="/etc/keys/ecryptfs-trusted.blob"
+--------------------------------------------------------------------------
+
+2) create the configuration file '/etc/sysconfig/ecryptfs' and set the ECRYPTFSKEY
+variable;
+
+3) specify the eCryptfs key path name in the 'ecryptfskey=' parameter of the kernel command
+line.
+
+# The configuration file '/etc/sysconfig/ecryptfs' is also used to specify
+# more options for mounting the eCryptfs filesystem:
+
+ECRYPTFSSRCDIR: existent directory in the lower root filesystem;
+ECRYPTFSDSTDIR: mount point directory for the eCryptfs filesystem (the directory must be
+ created in the root filesystem before rebooting the platform);
+ECRYPTFS_EXTRA_MOUNT_OPTS: extra mount options for the eCryptfs filesystem (the 'ecryptfs_sig'
+ option is automatically added by the dracut script).
+
+# Example of the configuration file:
+----------- '/etc/sysconfig/ecryptfs' (with default values) -----------
+ECRYPTFS_KEY="/etc/keys/ecryptfs-trusted.blob"
+ECRYPTFSSRCDIR="/secret"
+ECRYPTFSDSTDIR="${ECRYPTFSSRCDIR}"
+ECRYPTFS_EXTRA_MOUNT_OPTS=""
+-----------------------------------------------------------------------
+
+# If the variable ECRYPTFSDSTDIR is not specified in the configuration file,
+# its value will be equal to that of ECRYPTFSSRCDIR.
diff --git a/modules.d/98ecryptfs/ecryptfs-mount.sh b/modules.d/98ecryptfs/ecryptfs-mount.sh
new file mode 100755
index 0000000..0c1e228
--- /dev/null
+++ b/modules.d/98ecryptfs/ecryptfs-mount.sh
@@ -0,0 +1,95 @@
+#!/bin/sh
+
+# Licensed under the GPLv2
+#
+# Copyright (C) 2011 Politecnico di Torino, Italy
+# TORSEC group -- http://security.polito.it
+# Roberto Sassu <roberto.sassu@polito.it>
+
+ECRYPTFSCONFIG="${NEWROOT}/etc/sysconfig/ecryptfs"
+ECRYPTFSKEYTYPE="encrypted"
+ECRYPTFSKEYDESC="1000100010001000"
+ECRYPTFSKEYID=""
+ECRYPTFSSRCDIR="/secret"
+ECRYPTFS_EXTRA_MOUNT_OPTS=""
+
+load_ecryptfs_key() {
+ # override the eCryptfs key path name from the 'ecryptfskey=' parameter in the kernel
+ # command line
+ if ECRYPTFSKEYARG=$(getarg ecryptfskey=); then
+ ECRYPTFSKEY=${ECRYPTFSKEYARG}
+ fi
+
+ # set the default value
+ [ -z "${ECRYPTFSKEY}" ] \
+ && ECRYPTFSKEY="/etc/keys/ecryptfs-trusted.blob"
+
+ # set the eCryptfs key path name
+ ECRYPTFSKEYPATH="${NEWROOT}${ECRYPTFSKEY}"
+
+ # check for eCryptfs encrypted key's existence
+ if [ ! -f "${ECRYPTFSKEYPATH}" ]; then
+ if [ "${RD_DEBUG}" = "yes" ]; then
+ info "eCryptfs: key file not found: ${ECRYPTFSKEYPATH}"
+ fi
+ return 1
+ fi
+
+ # read the eCryptfs encrypted key blob
+ read -r KEYBLOB < "${ECRYPTFSKEYPATH}"
+
+ # load the eCryptfs encrypted key blob
+ if ! ECRYPTFSKEYID=$(keyctl add ${ECRYPTFSKEYTYPE} ${ECRYPTFSKEYDESC} "load ${KEYBLOB}" @u); then
+ info "eCryptfs: failed to load the eCryptfs key: ${ECRYPTFSKEYDESC}"
+ return 1
+ fi
+
+ return 0
+}
+
+unload_ecryptfs_key() {
+ # unlink the eCryptfs encrypted key
+ keyctl unlink "${ECRYPTFSKEYID}" @u || {
+ info "eCryptfs: failed to unlink the eCryptfs key: ${ECRYPTFSKEYDESC}"
+ return 1
+ }
+
+ return 0
+}
+
+mount_ecryptfs() {
+ # read the configuration from the config file
+ # shellcheck disable=SC1090
+ [ -f "${ECRYPTFSCONFIG}" ] \
+ && . "${ECRYPTFSCONFIG}"
+
+ # load the eCryptfs encrypted key
+ load_ecryptfs_key || return 1
+
+ # set the default value for ECRYPTFSDSTDIR
+ [ -z "${ECRYPTFSDSTDIR}" ] \
+ && ECRYPTFSDSTDIR=${ECRYPTFSSRCDIR}
+
+ # set the eCryptfs filesystem mount point
+ ECRYPTFSSRCMNT="${NEWROOT}${ECRYPTFSSRCDIR}"
+ ECRYPTFSDSTMNT="${NEWROOT}${ECRYPTFSDSTDIR}"
+
+ # build the mount options variable
+ ECRYPTFS_MOUNT_OPTS="ecryptfs_sig=${ECRYPTFSKEYDESC}"
+ [ -n "${ECRYPTFS_EXTRA_MOUNT_OPTS}" ] \
+ && ECRYPTFS_MOUNT_OPTS="${ECRYPTFS_MOUNT_OPTS},${ECRYPTFS_EXTRA_MOUNT_OPTS}"
+
+ # mount the eCryptfs filesystem
+ info "Mounting the configured eCryptfs filesystem"
+ mount -i -t ecryptfs -o${ECRYPTFS_MOUNT_OPTS} "${ECRYPTFSSRCMNT}" "${ECRYPTFSDSTMNT}" > /dev/null || {
+ info "eCryptfs: mount of the eCryptfs filesystem failed"
+ return 1
+ }
+
+ # unload the eCryptfs encrypted key
+ unload_ecryptfs_key || return 1
+
+ return 0
+}
+
+mount_ecryptfs
diff --git a/modules.d/98ecryptfs/module-setup.sh b/modules.d/98ecryptfs/module-setup.sh
new file mode 100755
index 0000000..9328b51
--- /dev/null
+++ b/modules.d/98ecryptfs/module-setup.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ return 255
+}
+
+# called by dracut
+depends() {
+ echo masterkey
+ return 0
+}
+
+# called by dracut
+installkernel() {
+ instmods ecryptfs
+}
+
+# called by dracut
+install() {
+ inst_hook pre-pivot 63 "$moddir/ecryptfs-mount.sh"
+}
diff --git a/modules.d/98integrity/README b/modules.d/98integrity/README
new file mode 100644
index 0000000..b16c6b6
--- /dev/null
+++ b/modules.d/98integrity/README
@@ -0,0 +1,68 @@
+# Directions for creating the encrypted key that will be used to initialize
+# the EVM software.
+
+# Create the EVM key (encrypted key type)
+#
+# The encrypted key is a random number encrypted/decrypted using the
+# kernel master key. The encrypted key is only exposed to userspace
+# as an encrypted datablob.
+$ keyctl add encrypted evm-key "new trusted:kmk-trusted 32" @u
+782117972
+
+# Save the encrypted key
+$ su -c 'keyctl pipe `keyctl search @u encrypted evm-key` > /etc/keys/evm-trusted.blob'
+
+# The EVM key path name can be set in one of the following ways (specified in
+# the order in which the variable is overwritten):
+
+1) use the default value:
+--------------------------------------------------------------------------
+EVMKEY="/etc/keys/evm-trusted.blob"
+--------------------------------------------------------------------------
+
+2) create the configuration file '/etc/sysconfig/evm' and set the EVMKEY variable;
+
+3) specify the EVM key path name in the 'evmkey=' parameter of the kernel command
+line.
+
+
+# Directions for loading a custom IMA policy.
+
+# Write the policy following the instructions provided in the file
+# 'Documentation/ABI/testing/ima_policy' of the kernel documentation.
+
+# Save the policy in a file.
+
+# Create the configuration file '/etc/sysconfig/ima' to override the path name of
+# the IMA custom policy.
+------------- '/etc/sysconfig/ima' (with the default value) -------------
+IMAPOLICY="/etc/sysconfig/ima-policy"
+-------------------------------------------------------------------------
+
+
+# Information on loading distro, third party or local keys on the trusted IMA keyring
+
+# Loading distro, third party or local keys on the trusted IMA keyring requires
+# creating a local certificate authority(local-CA), installing the local-CA's
+# public key on the system-keyring and signing the certificates with the local-CA
+# key.
+#
+# Many directions for creating a mini certificate authority exist on the web
+# (eg. openssl, yubikey). (Reminder: safely storing the private key offline is
+# really important, especially in the case of the local-CA's private key.) The
+# local-CA's public key can be loaded onto the system keyring either by building
+# the key into the kernel or, on Fedora, storing it in the UEFI/Mok keyring. (As
+# of writing, the patches for loading the UEFI/Mok keys on the system-keyring
+# have not been upstreamed.)
+#
+# To view the system keyring: keyctl show %keyring:.system_keyring
+#
+# Most on-line directions for signing certificates requires creating a Certificate
+# Signing Request (CSR). Creating such a request requires access to the private
+# key, which would not be available when signing distro or 3rd party certificates.
+# Openssl provides the "-ss_cert" option for directly signing certificates.
+
+# 98integrity/ima-keys-load.sh script loads the signed certificates stored
+# in the $IMAKEYSDIR onto the trusted IMA keyring. The default $IMAKEYSDIR
+# directory is /etc/keys/ima, but can be specified in the /etc/sysconfig/ima
+# policy.
diff --git a/modules.d/98integrity/evm-enable.sh b/modules.d/98integrity/evm-enable.sh
new file mode 100755
index 0000000..fbae5f3
--- /dev/null
+++ b/modules.d/98integrity/evm-enable.sh
@@ -0,0 +1,169 @@
+#!/bin/sh
+
+# Licensed under the GPLv2
+#
+# Copyright (C) 2011 Politecnico di Torino, Italy
+# TORSEC group -- http://security.polito.it
+# Roberto Sassu <roberto.sassu@polito.it>
+
+EVMSECFILE="${SECURITYFSDIR}/evm"
+EVMCONFIG="${NEWROOT}/etc/sysconfig/evm"
+EVMKEYDESC="evm-key"
+EVMKEYTYPE="encrypted"
+EVMKEYID=""
+EVM_ACTIVATION_BITS=0
+
+# The following variables can be set in /etc/sysconfig/evm:
+# EVMKEY: path to the symmetric key; defaults to /etc/keys/evm-trusted.blob
+# EVMKEYDESC: Description of the symmetric key; default is 'evm-key'
+# EVMKEYTYPE: Type of the symmetric key; default is 'encrypted'
+# EVMX509: path to x509 cert; default is /etc/keys/x509_evm.der
+# EVM_ACTIVATION_BITS: additional EVM activation bits, such as
+# EVM_SETUP_COMPLETE; default is 0
+# EVMKEYSDIR: Directory with more x509 certs; default is /etc/keys/evm/
+
+load_evm_key() {
+ # read the configuration from the config file
+ # shellcheck disable=SC1090
+ [ -f "${EVMCONFIG}" ] \
+ && . "${EVMCONFIG}"
+
+ # override the EVM key path name from the 'evmkey=' parameter in the kernel
+ # command line
+ if EVMKEYARG=$(getarg evmkey=); then
+ EVMKEY=${EVMKEYARG}
+ fi
+
+ # set the default value
+ [ -z "${EVMKEY}" ] \
+ && EVMKEY="/etc/keys/evm-trusted.blob"
+
+ # set the EVM key path name
+ EVMKEYPATH="${NEWROOT}${EVMKEY}"
+
+ # check for EVM encrypted key's existence
+ if [ ! -f "${EVMKEYPATH}" ]; then
+ if [ "${RD_DEBUG}" = "yes" ]; then
+ info "integrity: EVM encrypted key file not found: ${EVMKEYPATH}"
+ fi
+ return 1
+ fi
+
+ # read the EVM encrypted key blob
+ read -r KEYBLOB < "${EVMKEYPATH}"
+
+ # load the EVM encrypted key
+ if ! EVMKEYID=$(keyctl add ${EVMKEYTYPE} ${EVMKEYDESC} "load ${KEYBLOB}" @u); then
+ info "integrity: failed to load the EVM encrypted key: ${EVMKEYDESC}"
+ return 1
+ fi
+ return 0
+}
+
+load_evm_x509() {
+ info "Load EVM IMA X509"
+
+ # override the EVM key path name from the 'evmx509=' parameter in
+ # the kernel command line
+ if EVMX509ARG=$(getarg evmx509=); then
+ EVMX509=${EVMX509ARG}
+ fi
+
+ # set the default value
+ [ -z "${EVMX509}" ] \
+ && EVMX509="/etc/keys/x509_evm.der"
+
+ # set the EVM public key path name
+ EVMX509PATH="${NEWROOT}${EVMX509}"
+
+ # check for EVM public key's existence
+ if [ ! -f "${EVMX509PATH}" ]; then
+ EVMX509PATH=""
+ fi
+
+ local evm_pubid line
+ if line=$(keyctl describe %keyring:.evm); then
+ # the kernel already setup a trusted .evm keyring so use that one
+ evm_pubid=${line%%:*}
+ else
+ # look for an existing regular keyring
+ evm_pubid=$(keyctl search @u keyring _evm)
+ if [ -z "${evm_pubid}" ]; then
+ # create a new regular _evm keyring
+ evm_pubid=$(keyctl newring _evm @u)
+ fi
+ fi
+
+ if [ -z "${EVMKEYSDIR}" ]; then
+ EVMKEYSDIR="/etc/keys/evm"
+ fi
+ # load the default EVM public key onto the EVM keyring along
+ # with all the other ones in $EVMKEYSDIR
+ local key_imported=1
+ for PUBKEY in ${EVMX509PATH} "${NEWROOT}${EVMKEYSDIR}"/*; do
+ if [ ! -f "${PUBKEY}" ]; then
+ if [ "${RD_DEBUG}" = "yes" ]; then
+ info "integrity: EVM x509 cert file not found: ${PUBKEY}"
+ fi
+ continue
+ fi
+ if ! evmctl import "${PUBKEY}" "${evm_pubid}"; then
+ info "integrity: failed to load the EVM X509 cert ${PUBKEY}"
+ return 1
+ fi
+ key_imported=0
+ done
+
+ if [ "${RD_DEBUG}" = "yes" ]; then
+ keyctl show @u
+ fi
+
+ return ${key_imported}
+}
+
+unload_evm_key() {
+ # unlink the EVM encrypted key
+ keyctl unlink "${EVMKEYID}" @u || {
+ info "integrity: failed to unlink the EVM encrypted key: ${EVMKEYDESC}"
+ return 1
+ }
+
+ return 0
+}
+
+enable_evm() {
+ # check kernel support for EVM
+ if [ ! -e "${EVMSECFILE}" ]; then
+ if [ "${RD_DEBUG}" = "yes" ]; then
+ info "integrity: EVM kernel support is disabled"
+ fi
+ return 0
+ fi
+
+ local evm_configured=0
+ local EVM_INIT_HMAC=1 EVM_INIT_X509=2
+
+ # try to load the EVM encrypted key
+ load_evm_key && evm_configured=${EVM_INIT_HMAC}
+
+ # try to load the EVM public key
+ load_evm_x509 && evm_configured=$((evm_configured | EVM_INIT_X509))
+
+ # only enable EVM if a key or x509 certificate could be loaded
+ if [ $evm_configured -eq 0 ]; then
+ return 1
+ fi
+
+ # initialize EVM
+ info "Enabling EVM"
+ echo $((evm_configured | EVM_ACTIVATION_BITS)) > "${EVMSECFILE}"
+
+ if [ "$((evm_configured & EVM_INIT_HMAC))" -ne 0 ]; then
+ # unload the EVM encrypted key
+ unload_evm_key || return 1
+ fi
+
+ return 0
+}
+
+enable_evm
diff --git a/modules.d/98integrity/ima-keys-load.sh b/modules.d/98integrity/ima-keys-load.sh
new file mode 100755
index 0000000..2374550
--- /dev/null
+++ b/modules.d/98integrity/ima-keys-load.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+SECURITYFSDIR="/sys/kernel/security"
+IMASECDIR="${SECURITYFSDIR}/ima"
+IMACONFIG="${NEWROOT}/etc/sysconfig/ima"
+
+load_x509_keys() {
+ KEYRING_ID=$1
+
+ # override the default configuration
+ if [ -f "${IMACONFIG}" ]; then
+ # shellcheck disable=SC1090
+ . "${IMACONFIG}"
+ fi
+
+ if [ -z "${IMAKEYSDIR}" ]; then
+ IMAKEYSDIR="/etc/keys/ima"
+ fi
+
+ for PUBKEY in "${NEWROOT}${IMAKEYSDIR}"/*; do
+ # check for public key's existence
+ if [ ! -f "${PUBKEY}" ]; then
+ if [ "${RD_DEBUG}" = "yes" ]; then
+ info "integrity: IMA x509 cert file not found: ${PUBKEY}"
+ fi
+ continue
+ fi
+
+ if ! evmctl import "${PUBKEY}" "${KEYRING_ID}"; then
+ info "integrity: IMA x509 cert not loaded on keyring: ${PUBKEY}"
+ fi
+ done
+
+ if [ "${RD_DEBUG}" = "yes" ]; then
+ keyctl show "${KEYRING_ID}"
+ fi
+ return 0
+}
+
+# check kernel support for IMA
+if [ ! -e "${IMASECDIR}" ]; then
+ if [ "${RD_DEBUG}" = "yes" ]; then
+ info "integrity: IMA kernel support is disabled"
+ fi
+ return 0
+fi
+
+# get the IMA keyring id
+
+if line=$(keyctl describe %keyring:.ima); then
+ _ima_id=${line%%:*}
+else
+ _ima_id=$(keyctl search @u keyring _ima)
+ if [ -z "${_ima_id}" ]; then
+ _ima_id=$(keyctl newring _ima @u)
+ fi
+fi
+
+# load the IMA public key(s)
+load_x509_keys "${_ima_id}"
diff --git a/modules.d/98integrity/ima-policy-load.sh b/modules.d/98integrity/ima-policy-load.sh
new file mode 100755
index 0000000..a1fbb4d
--- /dev/null
+++ b/modules.d/98integrity/ima-policy-load.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+# Licensed under the GPLv2
+#
+# Copyright (C) 2011 Politecnico di Torino, Italy
+# TORSEC group -- http://security.polito.it
+# Roberto Sassu <roberto.sassu@polito.it>
+
+IMASECDIR="${SECURITYFSDIR}/ima"
+IMACONFIG="${NEWROOT}/etc/sysconfig/ima"
+IMAPOLICY="/etc/sysconfig/ima-policy"
+
+load_ima_policy() {
+ # check kernel support for IMA
+ if [ ! -e "${IMASECDIR}" ]; then
+ if [ "${RD_DEBUG}" = "yes" ]; then
+ info "integrity: IMA kernel support is disabled"
+ fi
+ return 0
+ fi
+
+ # override the default configuration
+ # shellcheck disable=SC1090
+ [ -f "${IMACONFIG}" ] \
+ && . "${IMACONFIG}"
+
+ # set the IMA policy path name
+ IMAPOLICYPATH="${NEWROOT}${IMAPOLICY}"
+
+ # check the existence of the IMA policy file
+ [ -f "${IMAPOLICYPATH}" ] && {
+ info "Loading the provided IMA custom policy"
+ printf '%s' "${IMAPOLICYPATH}" > "${IMASECDIR}"/policy \
+ || cat "${IMAPOLICYPATH}" > "${IMASECDIR}"/policy
+ }
+
+ return 0
+}
+
+load_ima_policy
diff --git a/modules.d/98integrity/module-setup.sh b/modules.d/98integrity/module-setup.sh
new file mode 100755
index 0000000..fb2badf
--- /dev/null
+++ b/modules.d/98integrity/module-setup.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ return 255
+}
+
+# called by dracut
+depends() {
+ echo masterkey securityfs
+ return 0
+}
+
+# called by dracut
+install() {
+ dracut_install evmctl keyctl
+ inst_hook pre-pivot 61 "$moddir/evm-enable.sh"
+ inst_hook pre-pivot 61 "$moddir/ima-keys-load.sh"
+ inst_hook pre-pivot 62 "$moddir/ima-policy-load.sh"
+}
diff --git a/modules.d/98pollcdrom/module-setup.sh b/modules.d/98pollcdrom/module-setup.sh
new file mode 100755
index 0000000..9684181
--- /dev/null
+++ b/modules.d/98pollcdrom/module-setup.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ return 255
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+# called by dracut
+install() {
+ inst_hook initqueue/settled 99 "$moddir/pollcdrom.sh"
+}
diff --git a/modules.d/98pollcdrom/pollcdrom.sh b/modules.d/98pollcdrom/pollcdrom.sh
new file mode 100755
index 0000000..85305a7
--- /dev/null
+++ b/modules.d/98pollcdrom/pollcdrom.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+# Licensed under the GPLv2
+#
+# Copyright 2008-2012, Red Hat, Inc.
+# Harald Hoyer <harald@redhat.com>
+
+if [ ! -e /sys/module/block/parameters/events_dfl_poll_msecs ]; then
+ # if the kernel does not support autopolling
+ # then we have to do a
+ # dirty hack for some cdrom drives,
+ # which report no medium for quiet
+ # some time.
+ for cdrom in /sys/block/sr*; do
+ [ -e "$cdrom" ] || continue
+ # skip, if cdrom medium was already found
+ strstr "$(udevadm info --query=property --path="${cdrom##/sys}")" \
+ ID_CDROM_MEDIA && continue
+ echo change > "$cdrom/uevent"
+ done
+fi
diff --git a/modules.d/98selinux/module-setup.sh b/modules.d/98selinux/module-setup.sh
new file mode 100755
index 0000000..3574b12
--- /dev/null
+++ b/modules.d/98selinux/module-setup.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ return 255
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+# called by dracut
+install() {
+ inst_hook pre-pivot 50 "$moddir/selinux-loadpolicy.sh"
+ inst_multiple setenforce chroot
+}
diff --git a/modules.d/98selinux/selinux-loadpolicy.sh b/modules.d/98selinux/selinux-loadpolicy.sh
new file mode 100755
index 0000000..0235b8e
--- /dev/null
+++ b/modules.d/98selinux/selinux-loadpolicy.sh
@@ -0,0 +1,70 @@
+#!/bin/sh
+
+# FIXME: load selinux policy. this should really be done after we switchroot
+
+rd_load_policy() {
+ # If SELinux is disabled exit now
+ getarg "selinux=0" > /dev/null && return 0
+
+ SELINUX="enforcing"
+ # shellcheck disable=SC1090
+ [ -e "$NEWROOT/etc/selinux/config" ] && . "$NEWROOT/etc/selinux/config"
+
+ # Check whether SELinux is in permissive mode
+ permissive=0
+
+ if getarg "enforcing=0" > /dev/null || [ "$SELINUX" = "permissive" ]; then
+ permissive=1
+ fi
+
+ # Attempt to load SELinux Policy
+ if [ -x "$NEWROOT/usr/sbin/load_policy" -o -x "$NEWROOT/sbin/load_policy" ]; then
+ local ret=0
+ local out
+ info "Loading SELinux policy"
+ mount -o bind /sys "$NEWROOT"/sys
+ # load_policy does mount /proc and /sys/fs/selinux in
+ # libselinux,selinux_init_load_policy()
+ if [ -x "$NEWROOT/sbin/load_policy" ]; then
+ out=$(LANG=C chroot "$NEWROOT" /sbin/load_policy -i 2>&1)
+ ret=$?
+ info "$out"
+ else
+ out=$(LANG=C chroot "$NEWROOT" /usr/sbin/load_policy -i 2>&1)
+ ret=$?
+ info "$out"
+ fi
+ umount "$NEWROOT"/sys/fs/selinux
+ umount "$NEWROOT"/sys
+
+ if [ "$SELINUX" = "disabled" ]; then
+ return 0
+ fi
+
+ if [ $ret -eq 0 -o $ret -eq 2 ]; then
+ # If machine requires a relabel, force to permissive mode
+ [ -e "$NEWROOT"/.autorelabel ] && LANG=C /usr/sbin/setenforce 0
+ mount --rbind /dev "$NEWROOT/dev"
+ LANG=C chroot "$NEWROOT" /sbin/restorecon -R /dev
+ umount -R "$NEWROOT/dev"
+ return 0
+ fi
+
+ warn "Initial SELinux policy load failed."
+ if [ $ret -eq 3 -o $permissive -eq 0 ]; then
+ warn "Machine in enforcing mode."
+ warn "Not continuing"
+ emergency_shell -n selinux
+ exit 1
+ fi
+ return 0
+ elif [ $permissive -eq 0 -a "$SELINUX" != "disabled" ]; then
+ warn "Machine in enforcing mode and cannot execute load_policy."
+ warn "To disable selinux, add selinux=0 to the kernel command line."
+ warn "Not continuing"
+ emergency_shell -n selinux
+ exit 1
+ fi
+}
+
+rd_load_policy
diff --git a/modules.d/98syslog/README b/modules.d/98syslog/README
new file mode 100644
index 0000000..9eb5ade
--- /dev/null
+++ b/modules.d/98syslog/README
@@ -0,0 +1,24 @@
+Syslog support for dracut
+
+This module provides syslog functionality in the initrd.
+This is especially interesting when complex configuration being
+used to provide access to the device the rootfs resides on.
+
+When this module is installed into the ramfs it is triggered by
+the udev event from the nic being setup (online).
+
+Then if syslog is configured it is started and will forward all
+kernel messages to the given syslog server.
+
+The syslog implementation is detected automatically by finding the
+appropriate binary with the following order:
+rsyslogd
+syslogd
+syslog-ng
+Then if detected the syslog.conf is generated and syslog is started.
+
+Bootparameters:
+syslogserver=ip Where to syslog to
+sysloglevel=level What level has to be logged
+syslogtype=rsyslog|syslog|syslogng
+ Don't auto detect syslog but set it
diff --git a/modules.d/98syslog/module-setup.sh b/modules.d/98syslog/module-setup.sh
new file mode 100755
index 0000000..2909a56
--- /dev/null
+++ b/modules.d/98syslog/module-setup.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ # do not add this module by default
+ return 255
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+# called by dracut
+install() {
+ local _installs
+ if find_binary rsyslogd > /dev/null; then
+ _installs="rsyslogd"
+ inst_libdir_file rsyslog/lmnet.so rsyslog/imklog.so rsyslog/imuxsock.so rsyslog/imjournal.so
+ elif find_binary syslogd > /dev/null; then
+ _installs="syslogd"
+ elif find_binary syslog-ng > /dev/null; then
+ _installs="syslog-ng"
+ else
+ derror "Could not find any syslog binary although the syslogmodule" \
+ "is selected to be installed. Please check."
+ fi
+ if [ -n "$_installs" ]; then
+ inst_multiple cat $_installs
+ inst_hook cmdline 90 "$moddir/parse-syslog-opts.sh"
+ inst_hook cleanup 99 "$moddir/syslog-cleanup.sh"
+ inst_hook initqueue/online 70 "$moddir/rsyslogd-start.sh"
+ inst_simple "$moddir/rsyslogd-stop.sh" /sbin/rsyslogd-stop
+ mkdir -m 0755 -p "${initdir}"/etc/templates
+ inst_simple "${moddir}/rsyslog.conf" /etc/templates/rsyslog.conf
+ fi
+ dracut_need_initqueue
+}
diff --git a/modules.d/98syslog/parse-syslog-opts.sh b/modules.d/98syslog/parse-syslog-opts.sh
new file mode 100755
index 0000000..ccefd9d
--- /dev/null
+++ b/modules.d/98syslog/parse-syslog-opts.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+# Parses the syslog commandline options
+#
+#Bootparameters:
+#syslogserver=ip Where to syslog to
+#sysloglevel=level What level has to be logged
+#syslogtype=rsyslog|syslog|syslogng
+# Don't auto detect syslog but set it
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+detect_syslog() {
+ syslogtype=""
+ if [ -e /sbin/rsyslogd ]; then
+ syslogtype="rsyslogd"
+ elif [ -e /sbin/syslogd ]; then
+ syslogtype="syslogd"
+ elif [ -e /sbin/syslog-ng ]; then
+ syslogtype="syslog-ng"
+ else
+ warn "Could not find any syslog binary although the syslogmodule is selected to be installed. Please check."
+ fi
+ echo "$syslogtype"
+ [ -n "$syslogtype" ]
+}
+
+syslogserver=$(getarg syslog.server -d syslog)
+syslogfilters=$(getargs syslog.filter -d filter)
+syslogtype=$(getarg syslog.type -d syslogtype)
+
+[ -n "$syslogserver" ] && echo "$syslogserver" > /tmp/syslog.server
+[ -n "$syslogfilters" ] && echo "$syslogfilters" > /tmp/syslog.filters
+if [ -n "$syslogtype" ]; then
+ echo "$syslogtype" > /tmp/syslog.type
+else
+ syslogtype=$(detect_syslog)
+ echo "$syslogtype" > /tmp/syslog.type
+fi
diff --git a/modules.d/98syslog/rsyslog.conf b/modules.d/98syslog/rsyslog.conf
new file mode 100644
index 0000000..218072b
--- /dev/null
+++ b/modules.d/98syslog/rsyslog.conf
@@ -0,0 +1,31 @@
+#rsyslog v3 config file
+
+# if you experience problems, check
+# http://www.rsyslog.com/troubleshoot for assistance
+
+#### MODULES ####
+
+$ModLoad imuxsock.so # provides support for local system logging (e.g. via logger command)
+$ModLoad imklog.so # provides kernel logging support (previously done by rklogd)
+#$ModLoad immark.so # provides --MARK-- message capability
+
+# Provides UDP syslog reception
+#$ModLoad imudp.so
+#$UDPServerRun 514
+
+# Provides TCP syslog reception
+#$ModLoad imtcp.so
+#$InputTCPServerRun 514
+
+
+#### GLOBAL DIRECTIVES ####
+
+# Use default timestamp format
+$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat
+
+# File syncing capability is disabled by default. This feature is usually not required,
+# not useful and an extreme performance hit
+#$ActionFileEnableSync on
+
+
+#### RULES ####
diff --git a/modules.d/98syslog/rsyslogd-start.sh b/modules.d/98syslog/rsyslogd-start.sh
new file mode 100755
index 0000000..d404e51
--- /dev/null
+++ b/modules.d/98syslog/rsyslogd-start.sh
@@ -0,0 +1,47 @@
+#!/bin/sh
+
+# Triggered by initqueue/online and starts rsyslogd with bootparameters
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+# prevent starting again if already running
+if [ -f /var/run/syslogd.pid ]; then
+ read -r pid < /var/run/syslogd.pid
+ kill -0 "$pid" && exit 0
+fi
+
+rsyslog_config() {
+ local server="$1"
+ shift
+ local syslog_template="$1"
+ shift
+ local filters="$*"
+ local filter=
+
+ cat "$syslog_template"
+
+ (
+ # disable shell expansion / globbing
+ # since filters contain such characters
+ set -f
+ for filter in $filters; do
+ echo "${filter} @${server}"
+ done
+ )
+ #echo "*.* /tmp/syslog"
+}
+
+[ -f /tmp/syslog.type ] && read -r type < /tmp/syslog.type
+[ -f /tmp/syslog.server ] && read -r server < /tmp/syslog.server
+[ -f /tmp/syslog.filters ] && read -r filters < /tmp/syslog.filters
+[ -z "$filters" ] && filters="kern.*"
+[ -f /tmp/syslog.conf ] && read -r conf < /tmp/syslog.conf
+[ -z "$conf" ] && conf="/etc/rsyslog.conf" && echo "$conf" > /tmp/syslog.conf
+
+if [ "$type" = "rsyslogd" ]; then
+ template=/etc/templates/rsyslog.conf
+ if [ -n "$server" ]; then
+ rsyslog_config "$server" "$template" "$filters" > $conf
+ rsyslogd -c3
+ fi
+fi
diff --git a/modules.d/98syslog/rsyslogd-stop.sh b/modules.d/98syslog/rsyslogd-stop.sh
new file mode 100755
index 0000000..3fc2a5f
--- /dev/null
+++ b/modules.d/98syslog/rsyslogd-stop.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+# Kills rsyslogd
+
+if [ -f /var/run/syslogd.pid ]; then
+ read -r pid < /var/run/syslogd.pid
+ kill "$pid"
+ kill -0 "$pid" && kill -9 "$pid"
+else
+ warn "rsyslogd-stop: Could not find a pid for rsyslogd. Won't kill it."
+fi
diff --git a/modules.d/98syslog/syslog-cleanup.sh b/modules.d/98syslog/syslog-cleanup.sh
new file mode 100755
index 0000000..2d08d8a
--- /dev/null
+++ b/modules.d/98syslog/syslog-cleanup.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+# Just cleans up a previously started syslogd
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+if [ -f /tmp/syslog.server ]; then
+ read -r syslogtype < /tmp/syslog.type
+ if command -v "${syslogtype}-stop" > /dev/null; then
+ "${syslogtype}"-stop
+ else
+ warn "syslog-cleanup: Could not find script to stop syslog of type \"$syslogtype\". Syslog will not be stopped."
+ fi
+fi
diff --git a/modules.d/98usrmount/module-setup.sh b/modules.d/98usrmount/module-setup.sh
new file mode 100755
index 0000000..bc88deb
--- /dev/null
+++ b/modules.d/98usrmount/module-setup.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ [[ $mount_needs ]] && return 1
+ return 0
+}
+
+# called by dracut
+depends() {
+ echo 'fs-lib'
+}
+
+# called by dracut
+install() {
+ if ! dracut_module_included "systemd"; then
+ inst_hook pre-pivot 50 "$moddir/mount-usr.sh"
+ fi
+ :
+}
diff --git a/modules.d/98usrmount/mount-usr.sh b/modules.d/98usrmount/mount-usr.sh
new file mode 100755
index 0000000..0a3eb32
--- /dev/null
+++ b/modules.d/98usrmount/mount-usr.sh
@@ -0,0 +1,110 @@
+#!/bin/sh
+
+type info > /dev/null 2>&1 || . /lib/dracut-lib.sh
+type fsck_single > /dev/null 2>&1 || . /lib/fs-lib.sh
+
+filtersubvol() {
+ local _oldifs
+ _oldifs="$IFS"
+ local IFS=","
+ # shellcheck disable=SC2086
+ set -- $1
+ IFS="$_oldifs"
+ while [ $# -gt 0 ]; do
+ case $1 in
+ 'subvol='*) : ;;
+ *) printf '%s' "${1}," ;;
+ esac
+ shift
+ done
+}
+
+fsck_usr() {
+ local _dev="$1"
+ local _fs="$2"
+ local _fsopts="$3"
+ local _fsckoptions
+
+ if [ -f "$NEWROOT"/fsckoptions ]; then
+ read -r _fsckoptions < "$NEWROOT"/fsckoptions
+ fi
+
+ if [ -f "$NEWROOT"/forcefsck ] || getargbool 0 forcefsck; then
+ _fsckoptions="-f $_fsckoptions"
+ elif [ -f "$NEWROOT"/.autofsck ]; then
+ # shellcheck disable=SC1090
+ [ -f "$NEWROOT"/etc/sysconfig/autofsck ] && . "$NEWROOT"/etc/sysconfig/autofsck
+ if [ "$AUTOFSCK_DEF_CHECK" = "yes" ]; then
+ AUTOFSCK_OPT="$AUTOFSCK_OPT -f"
+ fi
+ if [ -n "$AUTOFSCK_SINGLEUSER" ]; then
+ warn "*** Warning -- the system did not shut down cleanly. "
+ warn "*** Dropping you to a shell; the system will continue"
+ warn "*** when you leave the shell."
+ emergency_shell
+ fi
+ _fsckoptions="$AUTOFSCK_OPT $_fsckoptions"
+ fi
+
+ fsck_single "$_dev" "$_fs" "$_fsopts" "$_fsckoptions"
+}
+
+mount_usr() {
+ local _dev _mp _fs _opts _ _usr_found _ _freq _passno
+ # check, if we have to mount the /usr filesystem
+ while read -r _dev _mp _fs _opts _freq _passno || [ -n "$_dev" ]; do
+ [ "${_dev%%#*}" != "$_dev" ] && continue
+ if [ "$_mp" = "/usr" ]; then
+ case "$_dev" in
+ LABEL=* | UUID=* | PARTUUID=* | PARTLABEL=*)
+ _dev="$(label_uuid_to_dev "$_dev")"
+ ;;
+ *) ;;
+ esac
+
+ if strstr "$_opts" "subvol=" \
+ && [ "${root#block:}" -ef "$_dev" ] \
+ && [ -n "$rflags" ]; then
+ # for btrfs subvolumes we have to mount /usr with the same rflags
+ rflags=$(filtersubvol "$rflags")
+ rflags=${rflags%%,}
+ _opts="${_opts:+${_opts},}${rflags}"
+ elif getargbool 0 ro; then
+ # if "ro" is specified, we want /usr to be mounted read-only
+ _opts="${_opts:+${_opts},}ro"
+ elif getargbool 0 rw; then
+ # if "rw" is specified, we want /usr to be mounted read-write
+ _opts="${_opts:+${_opts},}rw"
+ fi
+ echo "$_dev ${NEWROOT}${_mp} $_fs ${_opts} $_freq $_passno"
+ _usr_found="1"
+ break
+ fi
+ done < "$NEWROOT/etc/fstab" >> /etc/fstab
+
+ if [ "$_usr_found" != "" ]; then
+ # we have to mount /usr
+ _fsck_ret=0
+ if ! getargbool 0 rd.skipfsck; then
+ if [ "0" != "${_passno:-0}" ]; then
+ fsck_usr "$_dev" "$_fs" "$_opts"
+ _fsck_ret=$?
+ [ $_fsck_ret -ne 255 ] && echo $_fsck_ret > /run/initramfs/usr-fsck
+ fi
+ fi
+
+ info "Mounting /usr with -o $_opts"
+ mount "$NEWROOT/usr" 2>&1 | vinfo
+
+ if ! ismounted "$NEWROOT/usr"; then
+ warn "Mounting /usr to $NEWROOT/usr failed"
+ warn "*** Dropping you to a shell; the system will continue"
+ warn "*** when you leave the shell."
+ emergency_shell
+ fi
+ fi
+}
+
+if [ -f "$NEWROOT/etc/fstab" ]; then
+ mount_usr
+fi
diff --git a/modules.d/99base/dracut-dev-lib.sh b/modules.d/99base/dracut-dev-lib.sh
new file mode 100755
index 0000000..5779508
--- /dev/null
+++ b/modules.d/99base/dracut-dev-lib.sh
@@ -0,0 +1,139 @@
+#!/bin/sh
+
+# replaces all occurrences of 'search' in 'str' with 'replacement'
+#
+# str_replace str search replacement
+#
+# example:
+# str_replace ' one two three ' ' ' '_'
+str_replace() {
+ local in="$1"
+ local s="$2"
+ local r="$3"
+ local out=''
+
+ while [ "${in##*"$s"*}" != "$in" ]; do
+ chop="${in%%"$s"*}"
+ out="${out}${chop}$r"
+ in="${in#*"$s"}"
+ done
+ printf -- '%s' "${out}${in}"
+}
+
+# get a systemd-compatible unit name from a path
+# (mimics unit_name_from_path_instance())
+dev_unit_name() {
+ local dev="$1"
+
+ if command -v systemd-escape > /dev/null; then
+ systemd-escape -p -- "$dev"
+ return $?
+ fi
+
+ if [ "$dev" = "/" -o -z "$dev" ]; then
+ printf -- "-"
+ return 0
+ fi
+
+ dev="${1%%/}"
+ dev="${dev##/}"
+ # shellcheck disable=SC1003
+ dev="$(str_replace "$dev" '\' '\x5c')"
+ dev="$(str_replace "$dev" '-' '\x2d')"
+ if [ "${dev##.}" != "$dev" ]; then
+ dev="\x2e${dev##.}"
+ fi
+ dev="$(str_replace "$dev" '/' '-')"
+
+ printf -- "%s" "$dev"
+}
+
+# set_systemd_timeout_for_dev [-n] <dev> [<timeout>]
+# Set 'rd.timeout' as the systemd timeout for <dev>
+set_systemd_timeout_for_dev() {
+ local _name
+ local _needreload
+ local _noreload
+ local _timeout
+
+ [ -z "$DRACUT_SYSTEMD" ] && return 0
+
+ if [ "$1" = "-n" ]; then
+ _noreload=1
+ shift
+ fi
+
+ if [ -n "$2" ]; then
+ _timeout="$2"
+ else
+ _timeout=$(getarg rd.timeout)
+ fi
+
+ _timeout=${_timeout:-0}
+
+ _name=$(dev_unit_name "$1")
+ if ! [ -L "${PREFIX}/etc/systemd/system/initrd.target.wants/${_name}.device" ]; then
+ [ -d "${PREFIX}"/etc/systemd/system/initrd.target.wants ] || mkdir -p "${PREFIX}"/etc/systemd/system/initrd.target.wants
+ ln -s ../"${_name}".device "${PREFIX}/etc/systemd/system/initrd.target.wants/${_name}.device"
+ type mark_hostonly > /dev/null 2>&1 && mark_hostonly /etc/systemd/system/initrd.target.wants/"${_name}".device
+ _needreload=1
+ fi
+
+ if ! [ -f "${PREFIX}/etc/systemd/system/${_name}.device.d/timeout.conf" ]; then
+ mkdir -p "${PREFIX}/etc/systemd/system/${_name}.device.d"
+ {
+ echo "[Unit]"
+ echo "JobTimeoutSec=$_timeout"
+ echo "JobRunningTimeoutSec=$_timeout"
+ } > "${PREFIX}/etc/systemd/system/${_name}.device.d/timeout.conf"
+ type mark_hostonly > /dev/null 2>&1 && mark_hostonly /etc/systemd/system/"${_name}".device.d/timeout.conf
+ _needreload=1
+ fi
+
+ if [ -z "$PREFIX" ] && [ "$_needreload" = 1 ] && [ -z "$_noreload" ]; then
+ /sbin/initqueue --onetime --unique --name daemon-reload systemctl daemon-reload
+ fi
+}
+
+# wait_for_dev <dev> [<timeout>]
+#
+# Installs a initqueue-finished script,
+# which will cause the main loop only to exit,
+# if the device <dev> is recognized by the system.
+wait_for_dev() {
+ local _name
+ local _noreload
+
+ if [ "$1" = "-n" ]; then
+ _noreload=-n
+ shift
+ fi
+
+ _name="$(str_replace "$1" '/' '\x2f')"
+
+ type mark_hostonly > /dev/null 2>&1 && mark_hostonly "$hookdir/initqueue/finished/devexists-${_name}.sh"
+
+ [ -e "${PREFIX}$hookdir/initqueue/finished/devexists-${_name}.sh" ] && return 0
+
+ printf '[ -e "%s" ]\n' "$1" \
+ >> "${PREFIX}$hookdir/initqueue/finished/devexists-${_name}.sh"
+ {
+ printf '[ -e "%s" ] || ' "$1"
+ printf 'warn "\"%s\" does not exist"\n' "$1"
+ } >> "${PREFIX}$hookdir/emergency/80-${_name}.sh"
+
+ set_systemd_timeout_for_dev $_noreload "$@"
+}
+
+cancel_wait_for_dev() {
+ local _name
+ _name="$(str_replace "$1" '/' '\x2f')"
+ rm -f -- "$hookdir/initqueue/finished/devexists-${_name}.sh"
+ rm -f -- "$hookdir/emergency/80-${_name}.sh"
+ if [ -n "$DRACUT_SYSTEMD" ]; then
+ _name=$(dev_unit_name "$1")
+ rm -f -- "${PREFIX}/etc/systemd/system/initrd.target.wants/${_name}.device"
+ rm -f -- "${PREFIX}/etc/systemd/system/${_name}.device.d/timeout.conf"
+ /sbin/initqueue --onetime --unique --name daemon-reload systemctl daemon-reload
+ fi
+}
diff --git a/modules.d/99base/dracut-lib.sh b/modules.d/99base/dracut-lib.sh
new file mode 100755
index 0000000..39609d8
--- /dev/null
+++ b/modules.d/99base/dracut-lib.sh
@@ -0,0 +1,1178 @@
+#!/bin/sh
+
+type wait_for_dev > /dev/null 2>&1 || . /lib/dracut-dev-lib.sh
+
+export DRACUT_SYSTEMD
+export NEWROOT
+if [ -n "$NEWROOT" ]; then
+ [ -d "$NEWROOT" ] || mkdir -p -m 0755 "$NEWROOT"
+fi
+
+# shellcheck disable=SC2153
+if [ -z "$PREFIX" ]; then
+ if ! [ -d /run/initramfs ]; then
+ mkdir -p -m 0755 /run/initramfs/log
+ ln -sfn /run/initramfs/log /var/log
+ fi
+
+ [ -d /run/lock ] || mkdir -p -m 0755 /run/lock
+ [ -d /run/log ] || mkdir -p -m 0755 /run/log
+fi
+
+debug_off() {
+ set +x
+}
+
+debug_on() {
+ [ "$RD_DEBUG" = "yes" ] && set -x
+}
+
+# returns OK if $1 contains literal string $2 (and isn't empty)
+strstr() {
+ [ "${1##*"$2"*}" != "$1" ]
+}
+
+# returns OK if $1 matches (completely) glob pattern $2
+# An empty $1 will not be considered matched, even if $2 is * which technically
+# matches; as it would match anything, it's not an interesting case.
+strglob() {
+ # shellcheck disable=SC2295
+ [ -n "$1" -a -z "${1##$2}" ]
+}
+
+# returns OK if $1 contains (anywhere) a match of glob pattern $2
+# An empty $1 will not be considered matched, even if $2 is * which technically
+# matches; as it would match anything, it's not an interesting case.
+strglobin() {
+ # shellcheck disable=SC2295
+ [ -n "$1" -a -z "${1##*$2*}" ]
+}
+
+# returns OK if $1 contains literal string $2 at the beginning, and isn't empty
+str_starts() {
+ [ "${1#"$2"*}" != "$1" ]
+}
+
+# returns OK if $1 contains literal string $2 at the end, and isn't empty
+str_ends() {
+ [ "${1%*"$2"}" != "$1" ]
+}
+
+trim() {
+ local var="$*"
+ var="${var#"${var%%[![:space:]]*}"}" # remove leading whitespace characters
+ var="${var%"${var##*[![:space:]]}"}" # remove trailing whitespace characters
+ printf "%s" "$var"
+}
+
+if [ -z "$DRACUT_SYSTEMD" ]; then
+
+ warn() {
+ check_quiet
+ echo "<28>dracut Warning: $*" > /dev/kmsg
+ echo "dracut Warning: $*" >&2
+ }
+
+ info() {
+ check_quiet
+ echo "<30>dracut: $*" > /dev/kmsg
+ if [ "$DRACUT_QUIET" != "yes" ]; then
+ echo "dracut: $*" >&2
+ fi
+ }
+
+else
+
+ warn() {
+ echo "Warning: $*" >&2
+ }
+
+ info() {
+ echo "$*"
+ }
+
+fi
+
+vwarn() {
+ while read -r line || [ -n "$line" ]; do
+ warn "$line"
+ done
+}
+
+vinfo() {
+ while read -r line || [ -n "$line" ]; do
+ info "$line"
+ done
+}
+
+killall_proc_mountpoint() {
+ local _pid
+ local _killed=0
+ for _pid in /proc/*; do
+ _pid=${_pid##/proc/}
+ case $_pid in
+ *[!0-9]*) continue ;;
+ esac
+ [ -e "/proc/$_pid/exe" ] || continue
+ [ -e "/proc/$_pid/root" ] || continue
+ if strstr "$(ls -l -- "/proc/$_pid" "/proc/$_pid/fd" 2> /dev/null)" "$1"; then
+ kill -9 "$_pid"
+ _killed=1
+ fi
+ done
+ return $_killed
+}
+
+getcmdline() {
+ local _line
+ local _i
+ local CMDLINE_ETC_D
+ local CMDLINE_ETC
+ local CMDLINE_PROC
+ unset _line
+
+ if [ -e /etc/cmdline ]; then
+ while read -r _line || [ -n "$_line" ]; do
+ CMDLINE_ETC="$CMDLINE_ETC $_line"
+ done < /etc/cmdline
+ fi
+ for _i in /etc/cmdline.d/*.conf; do
+ [ -e "$_i" ] || continue
+ while read -r _line || [ -n "$_line" ]; do
+ CMDLINE_ETC_D="$CMDLINE_ETC_D $_line"
+ done < "$_i"
+ done
+ if [ -e /proc/cmdline ]; then
+ while read -r _line || [ -n "$_line" ]; do
+ CMDLINE_PROC="$CMDLINE_PROC $_line"
+ done < /proc/cmdline
+ fi
+ CMDLINE="$CMDLINE_ETC_D $CMDLINE_ETC $CMDLINE_PROC"
+ printf "%s" "$CMDLINE"
+}
+
+getarg() {
+ debug_off
+ local _deprecated _newoption
+ CMDLINE=$(getcmdline)
+ export CMDLINE
+ while [ $# -gt 0 ]; do
+ case $1 in
+ -d)
+ _deprecated=1
+ shift
+ ;;
+ -y)
+ if dracut-getarg "$2" > /dev/null; then
+ if [ "$_deprecated" = "1" ]; then
+ if [ -n "$_newoption" ]; then
+ warn "Kernel command line option '$2' is deprecated, use '$_newoption' instead."
+ else
+ warn "Option '$2' is deprecated."
+ fi
+ fi
+ echo 1
+ debug_on
+ return 0
+ fi
+ _deprecated=0
+ shift 2
+ ;;
+ -n)
+ if dracut-getarg "$2" > /dev/null; then
+ echo 0
+ if [ "$_deprecated" = "1" ]; then
+ if [ -n "$_newoption" ]; then
+ warn "Kernel command line option '$2' is deprecated, use '$_newoption=0' instead."
+ else
+ warn "Option '$2' is deprecated."
+ fi
+ fi
+ debug_on
+ return 1
+ fi
+ _deprecated=0
+ shift 2
+ ;;
+ *)
+ if [ -z "$_newoption" ]; then
+ _newoption="$1"
+ fi
+ if dracut-getarg "$1"; then
+ if [ "$_deprecated" = "1" ]; then
+ if [ -n "$_newoption" ]; then
+ warn "Kernel command line option '$1' is deprecated, use '$_newoption' instead."
+ else
+ warn "Option '$1' is deprecated."
+ fi
+ fi
+ debug_on
+ return 0
+ fi
+ _deprecated=0
+ shift
+ ;;
+ esac
+ done
+ debug_on
+ return 1
+}
+
+# getargbool <defaultval> <args...>
+# False if "getarg <args...>" returns "0", "no", or "off".
+# True if getarg returns any other non-empty string.
+# If not found, assumes <defaultval> - usually 0 for false, 1 for true.
+# example: getargbool 0 rd.info
+# true: rd.info, rd.info=1, rd.info=xxx
+# false: rd.info=0, rd.info=off, rd.info not present (default val is 0)
+getargbool() {
+ local _b
+ unset _b
+ local _default
+ _default="$1"
+ shift
+ _b=$(getarg "$@") || _b=${_b:-"$_default"}
+ if [ -n "$_b" ]; then
+ [ "$_b" = "0" ] && return 1
+ [ "$_b" = "no" ] && return 1
+ [ "$_b" = "off" ] && return 1
+ fi
+ return 0
+}
+
+isdigit() {
+ case "$1" in
+ *[!0-9]* | "") return 1 ;;
+ esac
+
+ return 0
+}
+
+# getargnum <defaultval> <minval> <maxval> <arg>
+# Will echo the arg if it's in range [minval - maxval].
+# If it's not set or it's not valid, will set it <defaultval>.
+# Note all values are required to be >= 0 here.
+# <defaultval> should be with [minval -maxval].
+getargnum() {
+ local _b
+ unset _b
+ local _default _min _max
+ _default="$1"
+ shift
+ _min="$1"
+ shift
+ _max="$1"
+ shift
+ _b=$(getarg "$1") || _b=${_b:-"$_default"}
+ if [ -n "$_b" ]; then
+ isdigit "$_b" && _b=$((_b)) \
+ && [ $_b -ge "$_min" ] && [ $_b -le "$_max" ] && echo $_b && return
+ fi
+ echo "$_default"
+}
+
+getargs() {
+ debug_off
+ CMDLINE=$(getcmdline)
+ export CMDLINE
+ local _val _i _gfound _deprecated
+ unset _val
+ unset _gfound
+ _newoption="$1"
+ for _i in "$@"; do
+ if [ "$_i" = "-d" ]; then
+ _deprecated=1
+ continue
+ fi
+
+ if _val="$(dracut-getargs "$_i")"; then
+ if [ "$_deprecated" = "1" ]; then
+ if [ -n "$_newoption" ]; then
+ warn "Option '$_i' is deprecated, use '$_newoption' instead."
+ else
+ warn "Option $_i is deprecated!"
+ fi
+ fi
+ if [ -n "$_val" ]; then
+ printf '%s\n' "$_val"
+ fi
+ _gfound=1
+ fi
+ _deprecated=0
+ done
+ if [ -n "$_gfound" ]; then
+ debug_on
+ return 0
+ fi
+ debug_on
+ return 1
+}
+
+# Prints value of given option. If option is a flag and it's present,
+# it just returns 0. Otherwise 1 is returned.
+# $1 = options separated by commas
+# $2 = option we are interested in
+#
+# Example:
+# $1 = cipher=aes-cbc-essiv:sha256,hash=sha256,verify
+# $2 = hash
+# Output:
+# sha256
+getoptcomma() {
+ local line=",$1,"
+ local opt="$2"
+ local tmp
+
+ case "${line}" in
+ *,${opt}=*,*)
+ tmp="${line#*,"${opt}"=}"
+ echo "${tmp%%,*}"
+ return 0
+ ;;
+ *,${opt},*) return 0 ;;
+ esac
+ return 1
+}
+
+# Splits given string 'str' with separator 'sep' into variables 'var1', 'var2',
+# 'varN'. If number of fields is less than number of variables, remaining are
+# not set. If number of fields is greater than number of variables, the last
+# variable takes remaining fields. In short - it acts similarly to 'read'.
+#
+# splitsep sep str var1 var2 varN
+#
+# example:
+# splitsep ':' 'foo:bar:baz' v1 v2
+# in result:
+# v1='foo', v2='bar:baz'
+#
+# TODO: ':' inside fields.
+splitsep() {
+ debug_off
+ local sep="$1"
+ local str="$2"
+ shift 2
+ local tmp
+
+ while [ -n "$str" -a "$#" -gt 1 ]; do
+ tmp="${str%%"$sep"*}"
+ eval "$1='${tmp}'"
+ str="${str#"$tmp"}"
+ str="${str#"$sep"}"
+ shift
+ done
+ [ -n "$str" -a -n "$1" ] && eval "$1='$str'"
+ debug_on
+ return 0
+}
+
+setdebug() {
+ [ -f /usr/lib/initrd-release ] || return
+ if [ -z "$RD_DEBUG" ]; then
+ if [ -e /proc/cmdline ]; then
+ RD_DEBUG=no
+ if getargbool 0 rd.debug -d -y rdinitdebug -d -y rdnetdebug; then
+ RD_DEBUG=yes
+ [ -n "$BASH" ] \
+ && export PS4='${BASH_SOURCE}@${LINENO}(${FUNCNAME[0]-}): '
+ fi
+ fi
+ export RD_DEBUG
+ fi
+ debug_on
+}
+
+setdebug
+
+source_all() {
+ local f
+ local _dir
+ _dir=$1
+ shift
+ [ "$_dir" ] && [ -d "/$_dir" ] || return
+ for f in "/$_dir"/*.sh; do
+ if [ -e "$f" ]; then
+ # shellcheck disable=SC1090
+ # shellcheck disable=SC2240
+ . "$f" "$@"
+ fi
+ done
+}
+
+hookdir=/lib/dracut/hooks
+export hookdir
+
+source_hook() {
+ local _dir
+ _dir=$1
+ shift
+ source_all "/lib/dracut/hooks/$_dir" "$@"
+}
+
+check_finished() {
+ local f rc=0
+ for f in "$hookdir"/initqueue/finished/*.sh; do
+ [ "$f" = "$hookdir/initqueue/finished/*.sh" ] && return 0
+ # shellcheck disable=SC1090
+ if [ -e "$f" ] && (. "$f"); then
+ rm -f "$f"
+ else
+ rc=1
+ fi
+ done
+ return $rc
+}
+
+source_conf() {
+ local f
+ [ "$1" ] && [ -d "/$1" ] || return
+ # shellcheck disable=SC1090
+ for f in "/$1"/*.conf; do [ -e "$f" ] && . "$f"; done
+}
+
+die() {
+ {
+ echo "<24>dracut: FATAL: $*"
+ echo "<24>dracut: Refusing to continue"
+ } > /dev/kmsg
+
+ {
+ echo "warn dracut: FATAL: \"$*\""
+ echo "warn dracut: Refusing to continue"
+ } >> $hookdir/emergency/01-die.sh
+ [ -d /run/initramfs ] || mkdir -p -- /run/initramfs
+
+ : > /run/initramfs/.die
+
+ if getargbool 0 "rd.shell"; then
+ emergency_shell
+ else
+ source_hook "shutdown-emergency"
+ fi
+
+ if [ -n "$DRACUT_SYSTEMD" ]; then
+ systemctl --no-block --force halt
+ fi
+
+ exit 1
+}
+
+check_quiet() {
+ if [ -z "$DRACUT_QUIET" ]; then
+ DRACUT_QUIET="yes"
+ getargbool 0 rd.info -d -y rdinfo && DRACUT_QUIET="no"
+ getargbool 0 rd.debug -d -y rdinitdebug && DRACUT_QUIET="no"
+ getarg quiet || DRACUT_QUIET="yes"
+ a=$(getarg loglevel=)
+ [ -n "$a" ] && [ "$a" -ge 28 ] && DRACUT_QUIET="yes"
+ export DRACUT_QUIET
+ fi
+}
+
+check_occurances() {
+ # Count the number of times the character $ch occurs in $str
+ # Return 0 if the count matches the expected number, 1 otherwise
+ local str="$1"
+ local ch="$2"
+ local expected="$3"
+ local count=0
+
+ while [ "${str#*"$ch"}" != "${str}" ]; do
+ str="${str#*"$ch"}"
+ count=$((count + 1))
+ done
+
+ [ $count -eq "$expected" ]
+}
+
+incol2() {
+ debug_off
+ local check
+ local file="$1"
+ local str="$2"
+
+ [ -z "$file" ] && return 1
+ [ -z "$str" ] && return 1
+
+ while read -r _ check _ || [ -n "$check" ]; do
+ if [ "$check" = "$str" ]; then
+ debug_on
+ return 0
+ fi
+ done < "$file"
+ debug_on
+ return 1
+}
+
+udevsettle() {
+ # shellcheck disable=SC2086
+ udevadm settle --exit-if-exists=$hookdir/initqueue/work $settle_exit_if_exists
+}
+
+udevproperty() {
+ for i in "$@"; do
+ udevadm control --property="$i"
+ done
+}
+
+find_mount() {
+ local dev wanted_dev
+ wanted_dev="$(readlink -e -q "$1")"
+ while read -r dev _ || [ -n "$dev" ]; do
+ [ "$dev" = "$wanted_dev" ] && echo "$dev" && return 0
+ done < /proc/mounts
+ return 1
+}
+
+# usage: ismounted <mountpoint>
+# usage: ismounted /dev/<device>
+if command -v findmnt > /dev/null; then
+ ismounted() {
+ findmnt "$1" > /dev/null 2>&1
+ }
+else
+ ismounted() {
+ if [ -b "$1" ]; then
+ find_mount "$1" > /dev/null && return 0
+ return 1
+ fi
+
+ while read -r _ m _ || [ -n "$m" ]; do
+ [ "$m" = "$1" ] && return 0
+ done < /proc/mounts
+ return 1
+ }
+fi
+
+# Create udev rule match for a device with its device name, or the udev property
+# ID_FS_UUID or ID_FS_LABEL
+#
+# example:
+# udevmatch LABEL=boot
+# prints:
+# ENV{ID_FS_LABEL}="boot"
+#
+# TODO: symlinks
+udevmatch() {
+ case "$1" in
+ UUID=????????-????-????-????-???????????? | LABEL=* | PARTLABEL=* | PARTUUID=????????-????-????-????-????????????)
+ printf 'ENV{ID_FS_%s}=="%s"' "${1%%=*}" "${1#*=}"
+ ;;
+ UUID=*)
+ printf 'ENV{ID_FS_UUID}=="%s*"' "${1#*=}"
+ ;;
+ PARTUUID=*)
+ printf 'ENV{ID_FS_PARTUUID}=="%s*"' "${1#*=}"
+ ;;
+ /dev/?*) printf -- 'KERNEL=="%s"' "${1#/dev/}" ;;
+ *) return 255 ;;
+ esac
+}
+
+label_uuid_to_dev() {
+ local _dev
+ _dev="${1#block:}"
+ case "$_dev" in
+ LABEL=*)
+ echo "/dev/disk/by-label/$(echo "${_dev#LABEL=}" | sed 's,/,\\x2f,g;s, ,\\x20,g')"
+ ;;
+ PARTLABEL=*)
+ echo "/dev/disk/by-partlabel/$(echo "${_dev#PARTLABEL=}" | sed 's,/,\\x2f,g;s, ,\\x20,g')"
+ ;;
+ UUID=*)
+ echo "/dev/disk/by-uuid/${_dev#UUID=}"
+ ;;
+ PARTUUID=*)
+ echo "/dev/disk/by-partuuid/${_dev#PARTUUID=}"
+ ;;
+ *)
+ echo "$_dev"
+ ;;
+ esac
+}
+
+# Prints unique path for potential file inside specified directory. It consists
+# of specified directory, prefix and number at the end which is incremented
+# until non-existing file is found.
+#
+# funiq dir prefix
+#
+# example:
+# # ls /mnt
+# cdrom0 cdrom1
+#
+# # funiq /mnt cdrom
+# /mnt/cdrom2
+funiq() {
+ local dir="$1"
+ local prefix="$2"
+ local i=0
+
+ [ -d "${dir}" ] || return 1
+
+ while [ -e "${dir}/${prefix}$i" ]; do
+ i=$((i + 1)) || return 1
+ done
+
+ echo "${dir}/${prefix}$i"
+}
+
+# Creates unique directory and prints its path. It's using funiq to generate
+# path.
+#
+# mkuniqdir subdir new_dir_name
+mkuniqdir() {
+ local dir="$1"
+ local prefix="$2"
+ local retdir
+ local retdir_new
+
+ [ -d "${dir}" ] || mkdir -m 0755 -p "${dir}" || return 1
+
+ retdir=$(funiq "${dir}" "${prefix}") || return 1
+ until mkdir -m 0755 "${retdir}" 2> /dev/null; do
+ retdir_new=$(funiq "${dir}" "${prefix}") || return 1
+ [ "$retdir_new" = "$retdir" ] && return 1
+ retdir="$retdir_new"
+ done
+
+ echo "${retdir}"
+}
+
+# Copy the contents of SRC into DEST, merging the contents of existing
+# directories (kinda like rsync, or cpio -p).
+# Creates DEST if it doesn't exist. Overwrites files with the same names.
+#
+# copytree SRC DEST
+copytree() {
+ local src="$1" dest="$2"
+ [ -d "$src" ] || return 1
+ mkdir -p "$dest" || return 1
+ dest=$(readlink -e -q "$dest") || return 1
+ (
+ cd "$src" || exit 1
+ cp -af . -t "$dest"
+ )
+}
+
+# Evaluates command for UUIDs either given as arguments for this function or all
+# listed in /dev/disk/by-uuid. UUIDs doesn't have to be fully specified. If
+# beginning is given it is expanded to all matching UUIDs. To pass full UUID to
+# your command use '$___' as a place holder. Remember to escape '$'!
+#
+# foreach_uuid_until [ -p prefix ] command UUIDs
+#
+# prefix - string to put just before $___
+# command - command to be evaluated
+# UUIDs - list of UUIDs separated by space
+#
+# The function returns after *first successful evaluation* of the given command
+# with status 0. If evaluation fails for every UUID function returns with
+# status 1.
+#
+# Example:
+# foreach_uuid_until "mount -U \$___ /mnt; echo OK; umount /mnt" \
+# "01234 f512 a235567f-12a3-c123-a1b1-01234567abcb"
+foreach_uuid_until() (
+ cd /dev/disk/by-uuid || return 1
+
+ [ "$1" = -p ] && local prefix="$2" && shift 2
+ local cmd="$1"
+ shift
+ local uuids_list="$*"
+ local uuid
+ local full_uuid
+ local ___
+
+ [ -n "${cmd}" ] || return 1
+
+ for uuid in ${uuids_list:-*}; do
+ for full_uuid in "${uuid}"*; do
+ [ -e "${full_uuid}" ] || continue
+ # shellcheck disable=SC2034
+ ___="${prefix}${full_uuid}"
+ eval "${cmd}" && return 0
+ done
+ done
+
+ return 1
+)
+
+# Get kernel name for given device. Device may be the name too (then the same
+# is returned), a symlink (full path), UUID (prefixed with "UUID=") or label
+# (prefixed with "LABEL="). If just a beginning of the UUID is specified or
+# even an empty, function prints all device names which UUIDs match - every in
+# single line.
+#
+# NOTICE: The name starts with "/dev/".
+#
+# Example:
+# devnames UUID=123
+# May print:
+# /dev/dm-1
+# /dev/sdb1
+# /dev/sdf3
+devnames() {
+ local dev="$1"
+ local d
+ local names
+
+ case "$dev" in
+ UUID=*)
+ # shellcheck disable=SC2016
+ dev="$(foreach_uuid_until '! blkid -U $___' "${dev#UUID=}")" \
+ && return 255
+ [ -z "$dev" ] && return 255
+ ;;
+ LABEL=*) dev="$(blkid -L "${dev#LABEL=}")" || return 255 ;;
+ /dev/?*) ;;
+ *) return 255 ;;
+ esac
+
+ for d in $dev; do
+ names="$names
+$(readlink -e -q "$d")" || return 255
+ done
+
+ echo "${names#
+}"
+}
+
+usable_root() {
+ local _i
+
+ [ -d "$1" ] || return 1
+
+ for _i in "$1"/usr/lib*/ld-*.so "$1"/lib*/ld-*.so; do
+ [ -e "$_i" ] && return 0
+ done
+
+ for _i in proc sys dev; do
+ [ -e "$1"/$_i ] || return 1
+ done
+
+ return 0
+}
+
+inst_hook() {
+ local _hookname _unique _name _job _exe
+ while [ $# -gt 0 ]; do
+ case "$1" in
+ --hook)
+ _hookname="/$2"
+ shift
+ ;;
+ --unique)
+ _unique="yes"
+ ;;
+ --name)
+ _name="$2"
+ shift
+ ;;
+ *)
+ break
+ ;;
+ esac
+ shift
+ done
+
+ if [ -z "$_unique" ]; then
+ _job="${_name}$$"
+ else
+ _job="${_name:-$1}"
+ _job=${_job##*/}
+ fi
+
+ _exe=$1
+ shift
+
+ [ -x "$_exe" ] || _exe=$(command -v "$_exe")
+
+ if [ -n "$onetime" ]; then
+ {
+ # shellcheck disable=SC2016
+ echo '[ -e "$_job" ] && rm -f -- "$_job"'
+ echo "$_exe $*"
+ } > "/tmp/$$-${_job}.sh"
+ else
+ echo "$_exe $*" > "/tmp/$$-${_job}.sh"
+ fi
+
+ mv -f "/tmp/$$-${_job}.sh" "$hookdir/${_hookname}/${_job}.sh"
+}
+
+# inst_mount_hook <mountpoint> <prio> <name> <script>
+#
+# Install a mount hook with priority <prio>,
+# which executes <script> as soon as <mountpoint> is mounted.
+inst_mount_hook() {
+ local _prio="$2" _jobname="$3" _script="$4"
+ local _hookname
+ _hookname="mount-$(str_replace "$1" '/' '\\x2f')"
+ [ -d "$hookdir/${_hookname}" ] || mkdir -p "$hookdir/${_hookname}"
+ inst_hook --hook "$_hookname" --unique --name "${_prio}-${_jobname}" "$_script"
+}
+
+# wait_for_mount <mountpoint>
+#
+# Installs a initqueue-finished script,
+# which will cause the main loop only to exit,
+# if <mountpoint> is mounted.
+wait_for_mount() {
+ local _name
+ _name="$(str_replace "$1" '/' '\\x2f')"
+ printf '. /lib/dracut-lib.sh\nismounted "%s"\n' "$1" \
+ >> "$hookdir/initqueue/finished/ismounted-${_name}.sh"
+ {
+ printf 'ismounted "%s" || ' "$1"
+ printf 'warn "\"%s\" is not mounted"\n' "$1"
+ } >> "$hookdir/emergency/90-${_name}.sh"
+}
+
+killproc() {
+ debug_off
+ local _exe
+ _exe="$(command -v "$1")"
+ local _sig="$2"
+ local _i
+ [ -x "$_exe" ] || return 1
+ for _i in /proc/[0-9]*; do
+ [ "$_i" = "/proc/1" ] && continue
+ if [ -e "$_i"/_exe ] && [ "$_i/_exe" -ef "$_exe" ]; then
+ kill "$_sig" "${_i##*/}"
+ fi
+ done
+ debug_on
+}
+
+need_shutdown() {
+ : > /run/initramfs/.need_shutdown
+}
+
+wait_for_loginit() {
+ [ "$RD_DEBUG" = "yes" ] || return
+ [ -e /run/initramfs/loginit.pipe ] || return
+ debug_off
+ echo "DRACUT_LOG_END"
+ exec 0<> /dev/console 1<> /dev/console 2<> /dev/console
+ # wait for loginit
+ i=0
+ while [ $i -lt 10 ]; do
+ if [ ! -e /run/initramfs/loginit.pipe ]; then
+ j=$(jobs)
+ [ -z "$j" ] && break
+ [ -z "${j##*Running*}" ] || break
+ fi
+ sleep 0.1
+ i=$((i + 1))
+ done
+
+ if [ $i -eq 10 ]; then
+ kill %1 > /dev/null 2>&1
+ kill "$(while read -r line || [ -n "$line" ]; do echo "$line"; done < /run/initramfs/loginit.pid)"
+ fi
+
+ setdebug
+ rm -f -- /run/initramfs/loginit.pipe /run/initramfs/loginit.pid
+}
+
+# pidof version for root
+if ! command -v pidof > /dev/null 2> /dev/null; then
+ pidof() {
+ debug_off
+ local _cmd
+ local _exe
+ local _rl
+ local _ret=1
+ local i
+ _cmd="$1"
+ if [ -z "$_cmd" ]; then
+ debug_on
+ return 1
+ fi
+ _exe=$(command -v "$1")
+ for i in /proc/*/exe; do
+ [ -e "$i" ] || continue
+ if [ -n "$_exe" ]; then
+ [ "$i" -ef "$_exe" ] || continue
+ else
+ _rl=$(readlink -f "$i")
+ [ "${_rl%/"$_cmd"}" != "$_rl" ] || continue
+ fi
+ i=${i%/exe}
+ echo "${i##/proc/}"
+ _ret=0
+ done
+ debug_on
+ return $_ret
+ }
+fi
+
+_emergency_shell() {
+ local _name="$1"
+ if [ -n "$DRACUT_SYSTEMD" ]; then
+ : > /.console_lock
+ echo "PS1=\"$_name:\\\${PWD}# \"" > /etc/profile
+ systemctl start dracut-emergency.service
+ rm -f -- /etc/profile
+ rm -f -- /.console_lock
+ else
+ debug_off
+ source_hook "$hook"
+ echo
+ /sbin/rdsosreport
+ 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.'
+ if ! RD_DEBUG='' getargbool 0 rd.debug -d -y rdinitdebug -d -y rdnetdebug; then
+ echo
+ echo 'To get more debug information in the report,'
+ echo 'reboot with "rd.debug" added to the kernel command line.'
+ fi
+ echo
+ echo 'Dropping to debug shell.'
+ echo
+ export PS1="$_name:\${PWD}# "
+ [ -e /.profile ] || : > /.profile
+
+ _ctty="$(RD_DEBUG='' getarg rd.ctty=)" && _ctty="/dev/${_ctty##*/}"
+ if [ -z "$_ctty" ]; then
+ _ctty=console
+ while [ -f /sys/class/tty/$_ctty/active ]; do
+ read -r _ctty < /sys/class/tty/$_ctty/active
+ _ctty=${_ctty##* } # last one in the list
+ done
+ _ctty=/dev/$_ctty
+ fi
+ [ -c "$_ctty" ] || _ctty=/dev/tty1
+ case "$(/usr/bin/setsid --help 2>&1)" in *--ctty*) CTTY="--ctty" ;; esac
+ setsid $CTTY /bin/sh -i -l 0<> $_ctty 1<> $_ctty 2<> $_ctty
+ fi
+}
+
+emergency_shell() {
+ local _ctty
+ set +e
+ local _rdshell_name="dracut" action="Boot" hook="emergency"
+ local _emergency_action
+
+ if [ "$1" = "-n" ]; then
+ _rdshell_name=$2
+ shift 2
+ elif [ "$1" = "--shutdown" ]; then
+ _rdshell_name=$2
+ action="Shutdown"
+ hook="shutdown-emergency"
+ shift 2
+ fi
+
+ echo
+ echo
+ warn "$*"
+ echo
+
+ _emergency_action=$(getarg rd.emergency)
+ [ -z "$_emergency_action" ] \
+ && [ -e /run/initramfs/.die ] \
+ && _emergency_action=halt
+
+ if getargbool 1 rd.shell -d -y rdshell || getarg rd.break -d rdbreak; then
+ _emergency_shell "$_rdshell_name"
+ else
+ source_hook "$hook"
+ warn "$action has failed. To debug this issue add \"rd.shell rd.debug\" to the kernel command line."
+ [ -z "$_emergency_action" ] && _emergency_action=halt
+ fi
+
+ case "$_emergency_action" in
+ reboot)
+ reboot || exit 1
+ ;;
+ poweroff)
+ poweroff || exit 1
+ ;;
+ halt)
+ halt || exit 1
+ ;;
+ esac
+}
+
+# Retain the values of these variables but ensure that they are unexported
+# This is a POSIX-compliant equivalent of bash's "export -n"
+export_n() {
+ local var
+ local val
+ for var in "$@"; do
+ eval val=\$$var
+ unset $var
+ [ -n "$val" ] && eval "$var=\"$val\""
+ done
+}
+
+# returns OK if list1 contains all elements of list2, i.e. checks if list2 is a
+# sublist of list1. An order and a duplication doesn't matter.
+#
+# $1 = separator
+# $2 = list1
+# $3 = list2
+# $4 = ignore values, separated by $1
+listlist() {
+ local _sep="$1"
+ local _list="${_sep}${2}${_sep}"
+ local _sublist="$3"
+ [ -n "$4" ] && local _iglist="${_sep}${4}${_sep}"
+ local IFS="$_sep"
+ local _v
+
+ [ "$_list" = "$_sublist" ] && return 0
+
+ for _v in $_sublist; do
+ if [ -n "$_v" ] && ! ([ -n "$_iglist" ] && strstr "$_iglist" "$_v"); then
+ strstr "$_list" "$_v" || return 1
+ fi
+ done
+
+ return 0
+}
+
+# returns OK if both lists contain the same values. An order and a duplication
+# doesn't matter.
+#
+# $1 = separator
+# $2 = list1
+# $3 = list2
+# $4 = ignore values, separated by $1
+are_lists_eq() {
+ listlist "$1" "$2" "$3" "$4" && listlist "$1" "$3" "$2" "$4"
+}
+
+setmemdebug() {
+ if [ -z "$DEBUG_MEM_LEVEL" ]; then
+ DEBUG_MEM_LEVEL=$(getargnum 0 0 5 rd.memdebug)
+ export DEBUG_MEM_LEVEL
+ fi
+}
+
+setmemdebug
+
+# parameters: func log_level prefix msg [trace_level:trace]...
+make_trace_mem() {
+ local log_level prefix msg msg_printed
+ local trace trace_level trace_in_higher_levels insert_trace
+
+ msg=$1
+ shift
+
+ prefix='[debug_mem]'
+ log_level=$DEBUG_MEM_LEVEL
+
+ if [ -z "$log_level" ] || [ "$log_level" -le 0 ]; then
+ return
+ fi
+
+ # FIXME? useless echo?
+ # shellcheck disable=SC2116
+ msg=$(echo "$msg")
+
+ msg_printed=0
+ while [ $# -gt 0 ]; do
+ trace=${1%%:*}
+ trace_level=${trace%%+}
+ [ "$trace" != "$trace_level" ] && trace_in_higher_levels="yes"
+ trace=${1##*:}
+
+ if [ -z "$trace_level" ]; then
+ trace_level=0
+ fi
+
+ insert_trace=0
+ if [ -n "$trace_in_higher_levels" ]; then
+ if [ "$log_level" -ge "$trace_level" ]; then
+ insert_trace=1
+ fi
+ else
+ if [ "$log_level" -eq "$trace_level" ]; then
+ insert_trace=1
+ fi
+ fi
+
+ if [ $insert_trace -eq 1 ]; then
+ if [ $msg_printed -eq 0 ]; then
+ echo "$prefix $msg"
+ msg_printed=1
+ fi
+ show_memstats "$trace"
+ fi
+ shift
+ done
+}
+
+# parameters: type
+show_memstats() {
+ case $1 in
+ shortmem)
+ while read -r line || [ -n "$line" ]; do
+ str_starts "$line" "MemFree" \
+ || str_starts "$line" "Cached" \
+ || str_starts "$line" "Slab" \
+ || continue
+ echo "$line"
+ done < /proc/meminfo
+ ;;
+ mem)
+ cat /proc/meminfo
+ ;;
+ slab)
+ cat /proc/slabinfo
+ ;;
+ iomem)
+ cat /proc/iomem
+ ;;
+ esac
+}
+
+remove_hostonly_files() {
+ rm -fr /etc/cmdline /etc/cmdline.d/*.conf "$hookdir/initqueue/finished"
+ if [ -f /lib/dracut/hostonly-files ]; then
+ while read -r line || [ -n "$line" ]; do
+ [ -e "$line" ] || [ -h "$line" ] || continue
+ rm -f "$line"
+ done < /lib/dracut/hostonly-files
+ fi
+}
+
+# parameter: kernel_module [filesystem_name]
+# returns OK if kernel_module is loaded
+# modprobe fails if /lib/modules is not available (--no-kernel use case)
+load_fstype() {
+ local - fs _fs="${2:-$1}"
+ set +x
+ while read -r d fs || [ "$d" ]; do
+ [ "${fs:-$d}" = "$_fs" ] && return 0
+ done < /proc/filesystems
+ modprobe "$1"
+}
+
+# parameter: size of live image
+# calls emergency shell if ram size is too small for the image
+check_live_ram() {
+ minmem=$(getarg rd.minmem)
+ minmem=${minmem:-1024}
+ imgsize=$1
+ memsize=$(($(sed -n 's/MemTotal: *\([[:digit:]]*\).*/\1/p' /proc/meminfo) / 1024))
+
+ if [ -z "$imgsize" ]; then
+ warn "Image size could not be determined"
+ return 0
+ fi
+
+ if [ $((memsize - imgsize)) -lt "$minmem" ]; then
+ sed -i "N;/and attach it to a bug report./s/echo$/echo\n\
+ echo \n\
+ echo 'Warning!!!'\n\
+ echo 'The memory size of your system is too small for this live image.'\n\
+ echo 'Expect killed processes due to out of memory conditions.'\n\
+ echo \n/" /usr/bin/dracut-emergency
+
+ emergency_shell
+ fi
+}
diff --git a/modules.d/99base/init.sh b/modules.d/99base/init.sh
new file mode 100755
index 0000000..285059e
--- /dev/null
+++ b/modules.d/99base/init.sh
@@ -0,0 +1,399 @@
+#!/bin/sh
+#
+# Licensed under the GPLv2
+#
+# Copyright 2008-2010, Red Hat, Inc.
+# Harald Hoyer <harald@redhat.com>
+# Jeremy Katz <katzj@redhat.com>
+
+export -p > /tmp/export.orig
+
+NEWROOT="/sysroot"
+[ -d $NEWROOT ] || mkdir -p -m 0755 $NEWROOT
+
+OLDPATH=$PATH
+PATH=/usr/sbin:/usr/bin:/sbin:/bin
+export PATH
+
+# mount some important things
+if [ ! -d /proc/self ]; then
+ if ! mount -t proc -o nosuid,noexec,nodev proc /proc > /dev/null; then
+ echo "Cannot mount proc on /proc! Compile the kernel with CONFIG_PROC_FS!"
+ exit 1
+ fi
+fi
+
+if [ ! -d /sys/kernel ]; then
+ if ! mount -t sysfs -o nosuid,noexec,nodev sysfs /sys > /dev/null; then
+ echo "Cannot mount sysfs on /sys! Compile the kernel with CONFIG_SYSFS!"
+ exit 1
+ fi
+fi
+
+RD_DEBUG=""
+. /lib/dracut-lib.sh
+
+setdebug
+
+if ! ismounted /dev; then
+ mount -t devtmpfs -o mode=0755,noexec,nosuid,strictatime devtmpfs /dev > /dev/null
+fi
+
+if ! ismounted /dev; then
+ echo "Cannot mount devtmpfs on /dev! Compile the kernel with CONFIG_DEVTMPFS!"
+ exit 1
+fi
+
+# prepare the /dev directory
+[ ! -h /dev/fd ] && ln -s /proc/self/fd /dev/fd > /dev/null 2>&1
+[ ! -h /dev/stdin ] && ln -s /proc/self/fd/0 /dev/stdin > /dev/null 2>&1
+[ ! -h /dev/stdout ] && ln -s /proc/self/fd/1 /dev/stdout > /dev/null 2>&1
+[ ! -h /dev/stderr ] && ln -s /proc/self/fd/2 /dev/stderr > /dev/null 2>&1
+
+if ! ismounted /dev/pts; then
+ mkdir -m 0755 -p /dev/pts
+ mount -t devpts -o gid=5,mode=620,noexec,nosuid devpts /dev/pts > /dev/null
+fi
+
+if ! ismounted /dev/shm; then
+ mkdir -m 0755 -p /dev/shm
+ mount -t tmpfs -o mode=1777,noexec,nosuid,nodev,strictatime tmpfs /dev/shm > /dev/null
+fi
+
+if ! ismounted /run; then
+ mkdir -m 0755 -p /newrun
+ if ! str_starts "$(readlink -f /bin/sh)" "/run/"; then
+ mount -t tmpfs -o mode=0755,noexec,nosuid,nodev,strictatime tmpfs /newrun > /dev/null
+ else
+ # the initramfs binaries are located in /run, so don't mount it with noexec
+ mount -t tmpfs -o mode=0755,nosuid,nodev,strictatime tmpfs /newrun > /dev/null
+ fi
+ cp -a /run/* /newrun > /dev/null 2>&1
+ mount --move /newrun /run
+ rm -fr -- /newrun
+fi
+
+if command -v kmod > /dev/null 2> /dev/null; then
+ kmod static-nodes --format=tmpfiles 2> /dev/null \
+ | while read -r type file mode _ _ _ majmin || [ -n "$type" ]; do
+ type=${type%\!}
+ case $type in
+ d)
+ mkdir -m "$mode" -p "$file"
+ ;;
+ c)
+ mknod -m "$mode" "$file" "$type" "${majmin%:*}" "${majmin#*:}"
+ ;;
+ esac
+ done
+fi
+
+trap "emergency_shell Signal caught!" 0
+
+export UDEVRULESD=/run/udev/rules.d
+[ -d /run/udev ] || mkdir -p -m 0755 /run/udev
+[ -d "$UDEVRULESD" ] || mkdir -p -m 0755 "$UDEVRULESD"
+
+if [ "$RD_DEBUG" = "yes" ]; then
+ mkfifo /run/initramfs/loginit.pipe
+ loginit "$DRACUT_QUIET" < /run/initramfs/loginit.pipe > /dev/console 2>&1 &
+ exec > /run/initramfs/loginit.pipe 2>&1
+else
+ exec 0<> /dev/console 1<> /dev/console 2<> /dev/console
+fi
+
+[ -f /usr/lib/initrd-release ] && . /usr/lib/initrd-release
+[ -n "$VERSION_ID" ] && info "$NAME-$VERSION_ID"
+
+source_conf /etc/conf.d
+
+if getarg "rd.cmdline=ask"; then
+ echo "Enter additional kernel command line parameter (end with ctrl-d or .)"
+ while read -r -p "> " ${BASH:+-e} line || [ -n "$line" ]; do
+ [ "$line" = "." ] && break
+ echo "$line" >> /etc/cmdline.d/99-cmdline-ask.conf
+ done
+fi
+
+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
+ [ -f /tmp/99-cmdline-ask.conf ] && mv /tmp/99-cmdline-ask.conf /etc/cmdline.d/99-cmdline-ask.conf
+fi
+
+# run scriptlets to parse the command line
+make_trace_mem "hook cmdline" '1+:mem' '1+:iomem' '3+:slab'
+getarg 'rd.break=cmdline' -d 'rdbreak=cmdline' && emergency_shell -n cmdline "Break before cmdline"
+source_hook cmdline
+
+[ -z "$root" ] && die "No or empty root= argument"
+[ -z "$rootok" ] && die "Don't know how to handle 'root=$root'"
+
+export root rflags fstype netroot NEWROOT
+
+# pre-udev scripts run before udev starts, and are run only once.
+make_trace_mem "hook pre-udev" '1:shortmem' '2+:mem' '3+:slab'
+getarg 'rd.break=pre-udev' -d 'rdbreak=pre-udev' && emergency_shell -n pre-udev "Break before pre-udev"
+source_hook pre-udev
+
+UDEV_LOG=err
+getargbool 0 rd.udev.info -d -y rdudevinfo && UDEV_LOG=info
+getargbool 0 rd.udev.debug -d -y rdudevdebug && UDEV_LOG=debug
+
+# start up udev and trigger cold plugs
+UDEV_LOG=$UDEV_LOG "$systemdutildir"/systemd-udevd --daemon --resolve-names=never
+
+UDEV_QUEUE_EMPTY="udevadm settle --timeout=0"
+
+udevproperty "hookdir=$hookdir"
+
+make_trace_mem "hook pre-trigger" '1:shortmem' '2+:mem' '3+:slab'
+getarg 'rd.break=pre-trigger' -d 'rdbreak=pre-trigger' && emergency_shell -n pre-trigger "Break before pre-trigger"
+source_hook pre-trigger
+
+udevadm control --reload > /dev/null 2>&1 || :
+# then the rest
+udevadm trigger --type=subsystems --action=add > /dev/null 2>&1
+udevadm trigger --type=devices --action=add > /dev/null 2>&1
+
+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
+
+ udevsettle
+
+ 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
+
+ $UDEV_QUEUE_EMPTY > /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
+
+ $UDEV_QUEUE_EMPTY > /dev/null 2>&1 || continue
+
+ # no more udev jobs and queues empty.
+ sleep 0.5
+
+ if [ $main_loop -gt $((2 * RDRETRY / 3)) ]; then
+ 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
+ done
+ fi
+
+ main_loop=$((main_loop + 1))
+ [ $main_loop -gt $RDRETRY ] \
+ && {
+ flock -s 9
+ emergency_shell "Could not boot."
+ } 9> /.console_lock
+done
+unset job
+unset queuetriggered
+unset main_loop
+unset RDRETRY
+
+# pre-mount happens before we try to mount the root filesystem,
+# and happens once.
+make_trace_mem "hook pre-mount" '1:shortmem' '2+:mem' '3+:slab'
+getarg 'rd.break=pre-mount' -d 'rdbreak=pre-mount' && emergency_shell -n pre-mount "Break before pre-mount"
+source_hook pre-mount
+
+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_mount=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_mount=$((_i_mount + 1))
+ [ $_i_mount -gt 20 ] \
+ && {
+ flock -s 9
+ emergency_shell "Can't mount root filesystem"
+ } 9> /.console_lock
+done
+
+{
+ printf "Mounted root filesystem "
+ while read -r dev mp _ || [ -n "$dev" ]; do [ "$mp" = "$NEWROOT" ] && echo "$dev"; done < /proc/mounts
+} | vinfo
+
+# pre pivot scripts are sourced just before we doing cleanup and switch over
+# to the new root.
+make_trace_mem "hook pre-pivot" '1:shortmem' '2+:mem' '3+:slab'
+getarg 'rd.break=pre-pivot' -d 'rdbreak=pre-pivot' && emergency_shell -n pre-pivot "Break before pre-pivot"
+source_hook pre-pivot
+
+make_trace_mem "hook cleanup" '1:shortmem' '2+:mem' '3+:slab'
+# pre pivot cleanup scripts are sourced just before we switch over to the new root.
+getarg 'rd.break=cleanup' -d 'rdbreak=cleanup' && emergency_shell -n cleanup "Break before cleanup"
+source_hook cleanup
+
+# By the time we get here, the root filesystem should be mounted.
+# Try to find init.
+for i in "$(getarg real_init=)" "$(getarg init=)" $(getargs rd.distroinit=) /sbin/init; do
+ [ -n "$i" ] || continue
+
+ __p="${NEWROOT}/${i}"
+ if [ -h "$__p" ]; then
+ # relative links need to be left alone,
+ # while absolute links need to be resolved and prefixed.
+ __pt=$(readlink "$__p")
+ [ "${__pt#/}" = "$__pt" ] || __p="${NEWROOT}/$__pt"
+ fi
+ if [ -x "$__p" ]; then
+ INIT="$i"
+ break
+ fi
+done
+
+[ "$INIT" ] || {
+ echo "Cannot find init!"
+ echo "Please check to make sure you passed a valid root filesystem!"
+ emergency_shell
+}
+
+udevadm control --exit
+udevadm info --cleanup-db
+
+debug_off # Turn off debugging for this section
+
+CAPSH=$(command -v capsh)
+SWITCH_ROOT=$(command -v switch_root)
+
+# unexport some vars
+export_n root rflags fstype netroot NEWROOT
+unset CMDLINE
+
+# Clean up the environment
+for i in $(export -p); do
+ i=${i#declare -x}
+ i=${i#export}
+ strstr "$i" "=" || continue
+ i=${i%%=*}
+ [ -z "$i" ] && continue
+ case $i in
+ root | PATH | HOME | TERM | PS4 | RD_*)
+ :
+ ;;
+ *)
+ unset "$i"
+ ;;
+ esac
+done
+. /tmp/export.orig 2> /dev/null || :
+rm -f -- /tmp/export.orig
+
+initargs=""
+read -r CLINE < /proc/cmdline
+if getarg init= > /dev/null; then
+ ignoreargs="console BOOT_IMAGE"
+ # only pass arguments after init= to the init
+ CLINE=${CLINE#*init=}
+ # shellcheck disable=SC2086
+ set -- $CLINE
+ shift # clear out the rest of the "init=" arg
+ for x in "$@"; do
+ for s in $ignoreargs; do
+ [ "${x%%=*}" = "$s" ] && continue 2
+ done
+ initargs="$initargs $x"
+ done
+ unset CLINE
+else
+ debug_off # Turn off debugging for this section
+ # shellcheck disable=SC2086
+ set -- $CLINE
+ for x in "$@"; do
+ case "$x" in
+ [0-9] | s | S | single | emergency | auto)
+ initargs="$initargs $x"
+ ;;
+ esac
+ done
+fi
+debug_on
+
+if ! [ -d "$NEWROOT"/run ]; then
+ NEWRUN=/dev/.initramfs
+ mkdir -m 0755 -p "$NEWRUN"
+ mount --rbind /run/initramfs "$NEWRUN"
+fi
+
+wait_for_loginit
+
+# remove helper symlink
+[ -h /dev/root ] && rm -f -- /dev/root
+
+bv=$(getarg rd.break -d rdbreak) && [ -z "$bv" ] \
+ && emergency_shell -n switch_root "Break before switch_root"
+unset bv
+info "Switching root"
+
+unset PS4
+
+PATH=$OLDPATH
+export PATH
+
+if [ -f /etc/capsdrop ]; then
+ . /etc/capsdrop
+ info "Calling $INIT with capabilities $CAPS_INIT_DROP dropped."
+ unset RD_DEBUG
+ exec "$CAPSH" --drop="$CAPS_INIT_DROP" -- \
+ -c "exec \"$SWITCH_ROOT\" \"$NEWROOT\" \"$INIT\" $initargs" \
+ || {
+ warn "Command:"
+ warn capsh --drop="$CAPS_INIT_DROP" -- -c exec "$SWITCH_ROOT" "$NEWROOT" "$INIT" "$initargs"
+ warn "failed."
+ emergency_shell
+ }
+else
+ unset RD_DEBUG
+ # shellcheck disable=SC2086
+ exec "$SWITCH_ROOT" "$NEWROOT" "$INIT" $initargs || {
+ warn "Something went very badly wrong in the initramfs. Please "
+ warn "file a bug against dracut."
+ emergency_shell
+ }
+fi
diff --git a/modules.d/99base/initqueue.sh b/modules.d/99base/initqueue.sh
new file mode 100755
index 0000000..2c49079
--- /dev/null
+++ b/modules.d/99base/initqueue.sh
@@ -0,0 +1,72 @@
+#!/bin/sh
+#
+# Licensed under the GPLv2+
+#
+# Copyright 2008-2010, Red Hat, Inc.
+# Harald Hoyer <harald@redhat.com>
+
+PATH=/usr/sbin:/usr/bin:/sbin:/bin
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+while [ $# -gt 0 ]; do
+ case "$1" in
+ --onetime)
+ onetime="yes"
+ ;;
+ --online)
+ qname="/online"
+ ;;
+ --settled)
+ qname="/settled"
+ ;;
+ --finished)
+ qname="/finished"
+ ;;
+ --timeout)
+ qname="/timeout"
+ ;;
+ --unique)
+ unique="yes"
+ ;;
+ --name)
+ name="$2"
+ shift
+ ;;
+ --env)
+ env="$2"
+ shift
+ ;;
+ *)
+ break
+ ;;
+ esac
+ shift
+done
+
+if [ -z "$unique" ]; then
+ job="${name}$$"
+else
+ job="${name:-$1}"
+ job=${job##*/}
+fi
+
+exe=$1
+shift
+
+[ -x "$exe" ] || exe=$(command -v "$exe")
+if [ -z "$exe" ]; then
+ echo "Invalid command"
+ exit 1
+fi
+
+{
+ # shellcheck disable=SC2016
+ [ -n "$onetime" ] && echo '[ -e "$job" ] && rm -f -- "$job"'
+ [ -n "$env" ] && echo "$env"
+ echo "$exe" "$@"
+} > "/tmp/$$-${job}.sh"
+
+mv -f "/tmp/$$-${job}.sh" "$hookdir/initqueue${qname}/${job}.sh"
+[ -z "$qname" ] && : >> "$hookdir"/initqueue/work
+exit 0
diff --git a/modules.d/99base/loginit.sh b/modules.d/99base/loginit.sh
new file mode 100755
index 0000000..cdb305b
--- /dev/null
+++ b/modules.d/99base/loginit.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+# turn off debugging
+set +x
+
+QUIET=$1
+
+printf "%s" "$$" > /run/initramfs/loginit.pid
+
+# shellcheck disable=SC2015
+[ -e /dev/kmsg ] && exec 5> /dev/kmsg || exec 5> /dev/null
+exec 6> /run/initramfs/init.log
+
+while read -r line || [ -n "$line" ]; do
+ if [ "$line" = "DRACUT_LOG_END" ]; then
+ rm -f -- /run/initramfs/loginit.pipe
+ exit 0
+ fi
+ echo "<31>dracut: $line" >&5
+ # if "quiet" is specified we output to /dev/console
+ [ -n "$QUIET" ] || echo "dracut: $line"
+ echo "$line" >&6
+done
diff --git a/modules.d/99base/module-setup.sh b/modules.d/99base/module-setup.sh
new file mode 100755
index 0000000..54b0deb
--- /dev/null
+++ b/modules.d/99base/module-setup.sh
@@ -0,0 +1,146 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ return 0
+}
+
+# called by dracut
+depends() {
+ echo udev-rules
+ return 0
+}
+
+# called by dracut
+install() {
+ inst_multiple mount mknod mkdir sleep chown \
+ sed ls flock cp mv dmesg rm ln rmmod mkfifo umount readlink setsid \
+ modprobe chmod tr
+
+ inst_multiple -o findmnt less kmod
+
+ inst_binary "${dracutbasedir}/dracut-util" "/usr/bin/dracut-util"
+
+ 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'
+ grep '^root:' "$initdir/etc/passwd" > /dev/null 2>&1 || echo "root:$pwshadow:0:0::/root:/bin/sh" >> "$initdir/etc/passwd"
+ grep '^nobody:' "$dracutsysrootdir"/etc/passwd >> "$initdir/etc/passwd"
+
+ [[ $hostonly ]] && grep '^root:' "$dracutsysrootdir"/etc/shadow >> "$initdir/etc/shadow"
+
+ # install our scripts and hooks
+ inst_script "$moddir/init.sh" "/init"
+ inst_script "$moddir/initqueue.sh" "/sbin/initqueue"
+ inst_script "$moddir/loginit.sh" "/sbin/loginit"
+ inst_script "$moddir/rdsosreport.sh" "/sbin/rdsosreport"
+
+ [ -e "${initdir}/lib" ] || mkdir -m 0755 -p "${initdir}"/lib
+ mkdir -m 0755 -p "${initdir}"/lib/dracut
+ mkdir -m 0755 -p "${initdir}"/lib/dracut/hooks
+
+ mkdir -p "${initdir}"/tmp
+
+ inst_simple "$moddir/dracut-lib.sh" "/lib/dracut-lib.sh"
+ inst_simple "$moddir/dracut-dev-lib.sh" "/lib/dracut-dev-lib.sh"
+ mkdir -p "${initdir}"/var
+
+ if ! dracut_module_included "systemd"; then
+ inst_multiple switch_root || dfatal "Failed to install switch_root"
+ inst_hook cmdline 10 "$moddir/parse-root-opts.sh"
+ fi
+
+ if [[ $realinitpath ]]; then
+ for i in $realinitpath; do
+ echo "rd.distroinit=$i"
+ done > "${initdir}/etc/cmdline.d/distroinit.conf"
+ fi
+
+ ln -fs /proc/self/mounts "$initdir/etc/mtab"
+ if [[ $ro_mnt == yes ]]; then
+ echo ro >> "${initdir}/etc/cmdline.d/base.conf"
+ fi
+
+ [ -e "${initdir}/usr/lib" ] || mkdir -m 0755 -p "${initdir}"/usr/lib
+
+ local VERSION=""
+ local PRETTY_NAME=""
+ # Derive an os-release file from the host, if it exists
+ if [[ -e $dracutsysrootdir/etc/os-release ]]; then
+ # shellcheck disable=SC1090
+ . "$dracutsysrootdir"/etc/os-release
+ grep -hE -ve '^VERSION=' -ve '^PRETTY_NAME' "$dracutsysrootdir"/etc/os-release > "${initdir}"/usr/lib/initrd-release
+ [[ -n ${VERSION} ]] && VERSION+=" "
+ [[ -n ${PRETTY_NAME} ]] && PRETTY_NAME+=" "
+ else
+ # Fall back to synthesizing one, since dracut is presently used
+ # on non-systemd systems as well.
+ {
+ echo "NAME=dracut"
+ echo "ID=dracut"
+ echo "VERSION_ID=\"$DRACUT_VERSION\""
+ echo 'ANSI_COLOR="0;34"'
+ } > "${initdir}"/usr/lib/initrd-release
+ fi
+ VERSION+="dracut-$DRACUT_VERSION"
+ PRETTY_NAME+="dracut-$DRACUT_VERSION (Initramfs)"
+ {
+ echo "VERSION=\"$VERSION\""
+ echo "PRETTY_NAME=\"$PRETTY_NAME\""
+ # This addition is relatively new, intended to allow software
+ # to easily detect the dracut version if need be without
+ # having it mixed in with the real underlying OS version.
+ echo "DRACUT_VERSION=\"${DRACUT_VERSION}\""
+ } >> "$initdir"/usr/lib/initrd-release
+ echo "dracut-$DRACUT_VERSION" > "$initdir/lib/dracut/dracut-$DRACUT_VERSION"
+ ln -sf ../usr/lib/initrd-release "$initdir"/etc/initrd-release
+ ln -sf initrd-release "$initdir"/usr/lib/os-release
+ ln -sf initrd-release "$initdir"/etc/os-release
+
+ ## save host_devs which we need bring up
+ if [[ $hostonly_cmdline == "yes" ]]; then
+ if [[ -n ${host_devs[*]} ]]; then
+ dracut_need_initqueue
+ fi
+ if [[ -f $initdir/lib/dracut/need-initqueue ]] || ! dracut_module_included "systemd"; then
+ (
+ if dracut_module_included "systemd"; then
+ export DRACUT_SYSTEMD=1
+ fi
+ export PREFIX="$initdir"
+ export hookdir=/lib/dracut/hooks
+
+ # shellcheck source=dracut-dev-lib.sh
+ . "$moddir/dracut-dev-lib.sh"
+
+ for _dev in "${host_devs[@]}"; do
+ for _dev2 in "${root_devs[@]}"; do
+ [[ $_dev == "$_dev2" ]] && continue 2
+ done
+
+ # We only actually wait for real devs - swap is only needed
+ # for resume and udev rules generated when parsing resume=
+ # argument take care of the waiting for us
+ for _dev2 in "${swap_devs[@]}"; do
+ [[ $_dev == "$_dev2" ]] && continue 2
+ done
+
+ _pdev=$(get_persistent_dev "$_dev")
+
+ case "$_pdev" in
+ /dev/?*) wait_for_dev "$_pdev" 0 ;;
+ *) ;;
+ esac
+ done
+ )
+ fi
+ fi
+}
diff --git a/modules.d/99base/parse-root-opts.sh b/modules.d/99base/parse-root-opts.sh
new file mode 100755
index 0000000..9525249
--- /dev/null
+++ b/modules.d/99base/parse-root-opts.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+# shellcheck disable=SC2034
+root=$(getarg root=)
+
+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
diff --git a/modules.d/99base/rdsosreport.sh b/modules.d/99base/rdsosreport.sh
new file mode 100755
index 0000000..dadf30b
--- /dev/null
+++ b/modules.d/99base/rdsosreport.sh
@@ -0,0 +1,61 @@
+#!/bin/sh
+
+echo 'Generating "/run/initramfs/rdsosreport.txt"'
+
+[ -d /run/initramfs ] || mkdir -p /run/initramfs
+
+exec > /run/initramfs/rdsosreport.txt 2>&1
+
+PWFILTER='s/\(ftp:\/\/.*\):.*@/\1:*******@/g;s/\(cifs:\/\/.*\):.*@/\1:*******@/g;s/cifspass=[^ ]*/cifspass=*******/g;s/iscsi:.*@/iscsi:******@/g;s/rd.iscsi.password=[^ ]*/rd.iscsi.password=******/g;s/rd.iscsi.in.password=[^ ]*/rd.iscsi.in.password=******/g'
+set -x
+cat /lib/dracut/dracut-*
+
+echo "/proc/cmdline"
+sed -e "$PWFILTER" /proc/cmdline
+
+if [ -f /etc/cmdline ]; then
+ echo "/etc/cmdline"
+ sed -e "$PWFILTER" /etc/cmdline
+fi
+
+for _i in /etc/cmdline.d/*.conf; do
+ [ -f "$_i" ] || break
+ echo "$_i"
+ sed -e "$PWFILTER" "$_i"
+done
+
+cat /proc/self/mountinfo
+cat /proc/mounts
+
+blkid
+blkid -o udev
+
+ls -l /dev/disk/by*
+
+for _i in /etc/conf.d/*.conf; do
+ [ -f "$_i" ] || break
+ echo "$_i"
+ sed -e "$PWFILTER" "$_i"
+done
+
+if command -v lvm > /dev/null 2> /dev/null; then
+ lvm pvdisplay
+ lvm vgdisplay
+ lvm lvdisplay
+fi
+
+command -v dmsetup > /dev/null 2> /dev/null && dmsetup ls --tree
+
+cat /proc/mdstat
+
+command -v ip > /dev/null 2> /dev/null && ip addr
+
+if command -v journalctl > /dev/null 2> /dev/null; then
+ journalctl -ab --no-pager -o short-monotonic | sed -e "$PWFILTER"
+else
+ dmesg | sed -e "$PWFILTER"
+ if [ -f /run/initramfs/init.log ]; then
+ echo "/run/initramfs/init.log"
+ sed -e "$PWFILTER" /run/initramfs/init.log
+ fi
+fi
diff --git a/modules.d/99fs-lib/fs-lib.sh b/modules.d/99fs-lib/fs-lib.sh
new file mode 100755
index 0000000..c4640fa
--- /dev/null
+++ b/modules.d/99fs-lib/fs-lib.sh
@@ -0,0 +1,262 @@
+#!/bin/sh
+
+type getarg > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+fsck_ask_reboot() {
+ info "note - fsck suggests reboot, if you"
+ info "leave shell, booting will continue normally"
+ emergency_shell -n "(reboot ?)"
+}
+
+fsck_ask_err() {
+ warn "*** An error occurred during the file system check."
+ warn "*** Dropping you to a shell; the system will try"
+ warn "*** to mount the filesystem(s), when you leave the shell."
+ emergency_shell -n "(Repair filesystem)"
+}
+
+# inherits: _ret _drv _out
+fsck_tail() {
+ [ "$_ret" -gt 0 ] && warn "$_drv returned with $_ret"
+ if [ "$_ret" -ge 4 ]; then
+ [ -n "$_out" ] && echo "$_out" | vwarn
+ fsck_ask_err
+ else
+ [ -n "$_out" ] && echo "$_out" | vinfo
+ [ "$_ret" -ge 2 ] && fsck_ask_reboot
+ fi
+}
+
+# note: this function sets _drv of the caller
+fsck_able() {
+ case "$1" in
+ xfs)
+ # {
+ # type xfs_db &&
+ # type xfs_repair &&
+ # type xfs_check &&
+ # type mount &&
+ # type umount
+ # } >/dev/null 2>&1 &&
+ # _drv="_drv=none fsck_drv_xfs" &&
+ # return 0
+ return 1
+ ;;
+ ext?)
+ type e2fsck > /dev/null 2>&1 \
+ && _drv="fsck_drv_com e2fsck" \
+ && return 0
+ ;;
+ f2fs)
+ type fsck.f2fs > /dev/null 2>&1 \
+ && _drv="fsck_drv_com fsck.f2fs" \
+ && return 0
+ ;;
+ jfs)
+ type jfs_fsck > /dev/null 2>&1 \
+ && _drv="fsck_drv_com jfs_fsck" \
+ && return 0
+ ;;
+ reiserfs)
+ type reiserfsck > /dev/null 2>&1 \
+ && _drv="fsck_drv_com reiserfsck" \
+ && return 0
+ ;;
+ btrfs)
+ # type btrfsck >/dev/null 2>&1 &&
+ # _drv="_drv=none fsck_drv_btrfs" &&
+ # return 0
+ return 1
+ ;;
+ nfs*)
+ # nfs can be a nop, returning success
+ _drv=":" \
+ && return 0
+ ;;
+ *)
+ type fsck > /dev/null 2>&1 \
+ && _drv="fsck_drv_std fsck" \
+ && return 0
+ ;;
+ esac
+
+ return 1
+}
+
+# note: all drivers inherit: _drv _fop _dev
+
+fsck_drv_xfs() {
+ # xfs fsck is not necessary... Either it mounts or not
+ return 0
+}
+
+fsck_drv_btrfs() {
+ # btrfs fsck is not necessary... Either it mounts or not
+ return 0
+}
+
+# common code for checkers that follow usual subset of options and return codes
+fsck_drv_com() {
+ local _drv="$1"
+ local _ret
+ local _out
+
+ if ! strglobin "$_fop" "-[ynap]"; then
+ _fop="-a${_fop:+ "$_fop"}"
+ fi
+
+ info "issuing $_drv $_fop $_dev"
+ # we enforce non-interactive run, so $() is fine
+ # shellcheck disable=SC2086
+ _out=$($_drv $_fop "$_dev")
+ _ret=$?
+ fsck_tail
+
+ return $_ret
+}
+
+# code for generic fsck, if the filesystem checked is "unknown" to us
+fsck_drv_std() {
+ local _ret
+ local _out
+ unset _out
+
+ info "issuing fsck $_fop $_dev"
+ # note, we don't enforce -a here, thus fsck is being run (in theory)
+ # interactively; otherwise some tool might complain about lack of terminal
+ # (and using -a might not be safe)
+ # shellcheck disable=SC2086
+ fsck $_fop "$_dev" > /dev/console 2>&1
+ _ret=$?
+ fsck_tail
+
+ return $_ret
+}
+
+# checks single filesystem, relying on specific "driver"; we don't rely on
+# automatic checking based on fstab, so empty one is passed;
+# takes 4 arguments - device, filesystem, filesystem options, additional fsck options;
+# first 2 arguments are mandatory (fs may be auto or "")
+# returns 255 if filesystem wasn't checked at all (e.g. due to lack of
+# necessary tools or insufficient options)
+fsck_single() {
+ local FSTAB_FILE=/etc/fstab.empty
+ local _dev="$1"
+ local _fs="${2:-auto}"
+ local _fop="$4"
+ local _drv
+
+ [ $# -lt 2 ] && return 255
+ _dev=$(readlink -f "$(label_uuid_to_dev "$_dev")")
+ [ -e "$_dev" ] || return 255
+ _fs=$(det_fs "$_dev" "$_fs")
+ fsck_able "$_fs" || return 255
+
+ info "Checking $_fs: $_dev"
+ export FSTAB_FILE
+ eval "$_drv"
+ return $?
+}
+
+# takes list of filesystems to check in parallel; we don't rely on automatic
+# checking based on fstab, so empty one is passed
+fsck_batch() {
+ local FSTAB_FILE=/etc/fstab.empty
+ local _drv=fsck
+ local _dev
+ local _ret
+ local _out
+
+ [ $# -eq 0 ] || ! type fsck > /dev/null 2>&1 && return 255
+
+ info "Checking filesystems (fsck -M -T -a):"
+ for _dev in "$@"; do
+ info " $_dev"
+ done
+
+ export FSTAB_FILE
+ _out="$(fsck -M -T "$@" -- -a)"
+ _ret=$?
+
+ fsck_tail
+
+ return $_ret
+}
+
+# verify supplied filesystem type:
+# if user provided the fs and we couldn't find it, assume user is right
+# if we found the fs, assume we're right
+det_fs() {
+ local _dev="$1"
+ local _orig="${2:-auto}"
+ local _fs
+
+ _fs=$(udevadm info --query=property --name="$_dev" \
+ | while read -r line || [ -n "$line" ]; do
+ if str_starts "$line" "ID_FS_TYPE="; then
+ echo "${line#ID_FS_TYPE=}"
+ break
+ fi
+ done)
+ _fs=${_fs:-auto}
+
+ if [ "$_fs" = "auto" ]; then
+ _fs="$_orig"
+ fi
+ echo "$_fs"
+}
+
+write_fs_tab() {
+ local _o
+ local _rw
+ local _root
+ local _rootfstype
+ local _rootflags
+ local _fspassno
+
+ _fspassno="0"
+ _root="$1"
+ _rootfstype="$2"
+ _rootflags="$3"
+ [ -z "$_rootfstype" ] && _rootfstype=$(getarg rootfstype=)
+ [ -z "$_rootflags" ] && _rootflags=$(getarg rootflags=)
+
+ [ -z "$_rootfstype" ] && _rootfstype="auto"
+
+ if [ -z "$_rootflags" ]; then
+ _rootflags="ro,x-initrd.mount"
+ else
+ _rootflags="ro,$_rootflags,x-initrd.mount"
+ fi
+
+ _rw=0
+
+ CMDLINE=$(getcmdline)
+ for _o in $CMDLINE; do
+ case $_o in
+ rw)
+ _rw=1
+ ;;
+ ro)
+ _rw=0
+ ;;
+ esac
+ done
+ if [ "$_rw" = "1" ]; then
+ _rootflags="$_rootflags,rw"
+ if ! getargbool 0 rd.skipfsck; then
+ _fspassno="1"
+ fi
+ fi
+
+ if grep -q "$_root /sysroot" /etc/fstab; then
+ echo "$_root /sysroot $_rootfstype $_rootflags $_fspassno 0" >> /etc/fstab
+ else
+ return
+ fi
+
+ if type systemctl > /dev/null 2> /dev/null; then
+ systemctl daemon-reload
+ systemctl --no-block start initrd-root-fs.target
+ fi
+}
diff --git a/modules.d/99fs-lib/module-setup.sh b/modules.d/99fs-lib/module-setup.sh
new file mode 100755
index 0000000..2b81b0c
--- /dev/null
+++ b/modules.d/99fs-lib/module-setup.sh
@@ -0,0 +1,89 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ return 0
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+echo_fs_helper() {
+ local fs=$2
+ case "$fs" in
+ xfs)
+ echo -n " xfs_db xfs_repair xfs_check xfs_metadump "
+ ;;
+ ext?)
+ echo -n " e2fsck "
+ ;;
+ jfs)
+ echo -n " jfs_fsck "
+ ;;
+ reiserfs)
+ echo -n " reiserfsck "
+ ;;
+ btrfs)
+ echo -n " btrfsck "
+ ;;
+ esac
+
+ echo -n " fsck.$fs "
+ return 0
+}
+
+include_fs_helper_modules() {
+ local fs=$2
+ case "$fs" in
+ xfs | btrfs | ext4 | ext3)
+ instmods crc32c
+ ;;
+ f2fs)
+ instmods crc32
+ ;;
+ esac
+}
+
+# called by dracut
+installkernel() {
+ # xfs/btrfs/ext4 need crc32c, f2fs needs crc32
+ if [[ $hostonly ]]; then
+ for_each_host_dev_fs include_fs_helper_modules
+ :
+ else
+ instmods crc32c crc32
+ fi
+}
+
+# called by dracut
+install() {
+ local _helpers
+
+ inst "$moddir/fs-lib.sh" "/lib/fs-lib.sh"
+ : > "${initdir}"/etc/fstab.empty
+
+ [[ $nofscks == "yes" ]] && return
+
+ if [[ $fscks == "${fscks#*[^ ]*}" ]]; then
+ _helpers=(
+ /sbin/fsck* /usr/sbin/fsck*
+ xfs_db xfs_check xfs_repair xfs_metadump
+ e2fsck jfs_fsck reiserfsck btrfsck
+ )
+ if [[ $hostonly ]]; then
+ read -r -a _helpers < <(for_each_host_dev_fs echo_fs_helper)
+ fi
+ else
+ read -r -a _helpers <<< "$fscks"
+ fi
+
+ _helpers+=(umount mount)
+
+ if [[ ${_helpers[*]} == *e2fsck* ]] && [[ -e $dracutsysrootdir/etc/e2fsck.conf ]]; then
+ inst_simple /etc/e2fsck.conf
+ fi
+
+ inst_multiple -o "${_helpers[@]}" fsck
+}
diff --git a/modules.d/99img-lib/img-lib.sh b/modules.d/99img-lib/img-lib.sh
new file mode 100755
index 0000000..4700832
--- /dev/null
+++ b/modules.d/99img-lib/img-lib.sh
@@ -0,0 +1,108 @@
+#!/bin/sh
+# img-lib.sh: utilities for dealing with archives and filesystem images.
+#
+# TODO: identify/unpack rpm, deb, maybe others?
+
+# super-simple "file" that only identifies archives.
+# works with stdin if $1 is not set.
+det_archive() {
+ # NOTE: internal echo -e works in ash and bash, but not dash
+ local bz xz gz zs
+ local headerblock
+ bz="BZh"
+ # shellcheck disable=SC3037
+ xz="$(/bin/echo -e '\xfd7zXZ')"
+ # shellcheck disable=SC3037
+ gz="$(/bin/echo -e '\x1f\x8b')"
+ # shellcheck disable=SC3037
+ zs="$(/bin/echo -e '\x28\xB5\x2F\xFD')"
+ headerblock="$(dd ${1:+if=$1} bs=262 count=1 2> /dev/null | tr -d '\0')"
+ case "$headerblock" in
+ $xz*) echo "xz" ;;
+ $gz*) echo "gzip" ;;
+ $bz*) echo "bzip2" ;;
+ $zs*) echo "zstd" ;;
+ 07070*) echo "cpio" ;;
+ *ustar) echo "tar" ;;
+ esac
+}
+
+# determine filesystem type for a filesystem image
+det_fs_img() {
+ local dev
+ dev=$(losetup --find --show "$1") rv=""
+ det_fs "$dev"
+ rv=$?
+ losetup -d "$dev"
+ return $rv
+}
+
+# unpack_archive ARCHIVE OUTDIR
+# unpack a (possibly compressed) cpio/tar archive
+unpack_archive() {
+ local img="$1" outdir="$2" archiver="" decompr=""
+ local ft
+ ft="$(det_archive "$img")"
+ case "$ft" in
+ xz | gzip | bzip2 | zstd) decompr="$ft -dc" ;;
+ cpio | tar) decompr="cat" ;;
+ *) return 1 ;;
+ esac
+ ft="$($decompr "$img" | det_archive)"
+ case "$ft" in
+ cpio) archiver="cpio -iumd" ;;
+ tar) archiver="tar -xf -" ;;
+ *) return 2 ;;
+ esac
+ mkdir -p "$outdir"
+ (
+ cd "$outdir" || exit
+ $decompr | $archiver 2> /dev/null
+ ) < "$img"
+}
+
+# unpack_fs FSIMAGE OUTDIR
+# unpack a filesystem image
+unpack_fs() {
+ local img="$1" outdir="$2"
+ local mnt
+ mnt="$(mkuniqdir /tmp unpack_fs.)"
+ mount -o loop "$img" "$mnt" || {
+ rmdir "$mnt"
+ return 1
+ }
+ mkdir -p "$outdir"
+ outdir="$(
+ cd "$outdir" || exit
+ pwd
+ )"
+ copytree "$mnt" "$outdir"
+ umount "$mnt"
+ rmdir "$mnt"
+}
+
+# unpack an image file - compressed/uncompressed cpio/tar, filesystem, whatever
+# unpack_img IMAGEFILE OUTDIR
+unpack_img() {
+ local img="$1" outdir="$2"
+ [ -r "$img" ] || {
+ warn "can't read img!"
+ return 1
+ }
+ [ -n "$outdir" ] || {
+ warn "unpack_img: no output dir given"
+ return 1
+ }
+
+ if [ "$(det_archive "$img")" ]; then
+ unpack_archive "$@" || {
+ warn "can't unpack archive file!"
+ return 1
+ }
+ else
+ unpack_fs "$@" || {
+ warn "can't unpack filesystem image!"
+ return 1
+ }
+ fi
+}
diff --git a/modules.d/99img-lib/module-setup.sh b/modules.d/99img-lib/module-setup.sh
new file mode 100755
index 0000000..4f57b37
--- /dev/null
+++ b/modules.d/99img-lib/module-setup.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+# module-setup for img-lib
+
+# called by dracut
+check() {
+ require_binaries tar gzip dd echo tr || return 1
+ return 255
+}
+
+# called by dracut
+depends() {
+ return 0
+}
+
+# called by dracut
+install() {
+ inst_multiple tar gzip dd echo tr rmdir
+ # TODO: make this conditional on a cmdline flag / config option
+ inst_multiple -o cpio xz bzip2 zstd
+ inst_simple "$moddir/img-lib.sh" "/lib/img-lib.sh"
+}
diff --git a/modules.d/99memstrack/memstrack-report.sh b/modules.d/99memstrack/memstrack-report.sh
new file mode 100755
index 0000000..0ee7f2f
--- /dev/null
+++ b/modules.d/99memstrack/memstrack-report.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+. /lib/dracut-lib.sh
+
+if ! [ "$DEBUG_MEM_LEVEL" -ge 4 ]; then
+ return 0
+fi
+
+if command -v systemctl > /dev/null; then
+ systemctl stop memstrack.service
+else
+ pkill --signal INT '[m]emstrack'
+ while pgrep -c '[m]emstrack' > /dev/null; do
+ sleep 1
+ done
+fi
+
+cat /.memstrack
diff --git a/modules.d/99memstrack/memstrack-start.sh b/modules.d/99memstrack/memstrack-start.sh
new file mode 100755
index 0000000..45f65c2
--- /dev/null
+++ b/modules.d/99memstrack/memstrack-start.sh
@@ -0,0 +1,65 @@
+#!/bin/sh
+# Mount kernel debug fs so debug tools can work.
+# memdebug=4 and memdebug=5 requires debug fs to be mounted.
+# And there is no need to umount it.
+
+type getargnum > /dev/null 2>&1 || . /lib/dracut-lib.sh
+
+# "sys/kernel/tracing" has the priority if exists.
+get_trace_base() {
+ # trace access through debugfs would be obsolete if "/sys/kernel/tracing" is available.
+ if [ -d "/sys/kernel/tracing" ]; then
+ echo "/sys/kernel"
+ else
+ echo "/sys/kernel/debug"
+ fi
+}
+
+is_debugfs_ready() {
+ [ -f "$(get_trace_base)/tracing/trace" ]
+}
+
+prepare_debugfs() {
+ trace_base=$(get_trace_base)
+ # old debugfs interface case.
+ if ! [ -d "$trace_base/tracing" ]; then
+ mount none -t debugfs "$trace_base"
+ # new tracefs interface case.
+ elif ! [ -f "$trace_base/tracing/trace" ]; then
+ mount none -t tracefs "$trace_base/tracing"
+ fi
+
+ if ! [ -f "$trace_base/tracing/trace" ]; then
+ echo "WARN: failed to mount debugfs"
+ return 1
+ fi
+}
+
+if ! is_debugfs_ready; then
+ prepare_debugfs
+fi
+
+if [ -n "$DEBUG_MEM_LEVEL" ]; then
+ if [ "$DEBUG_MEM_LEVEL" -ge 5 ]; then
+ echo "memstrack - will report kernel module memory usage summary and top allocation stack"
+ nohup memstrack --report module_summary,module_top --notui --throttle 80 -o /.memstrack > /dev/null &
+ elif [ "$DEBUG_MEM_LEVEL" -ge 4 ]; then
+ echo "memstrack - will report memory usage summary"
+ nohup memstrack --report module_summary --notui --throttle 80 -o /.memstrack > /dev/null &
+ else
+ exit 0
+ fi
+fi
+
+PID=$!
+RET=$?
+
+if [ $RET -ne 0 ]; then
+ echo "Failed to start memstrack, exit status: $RET"
+ exit $RET
+fi
+
+echo $PID > /run/memstrack.pid
+
+# Wait a second for memstrack to setup everything, avoid missing any event
+sleep 1
diff --git a/modules.d/99memstrack/memstrack.service b/modules.d/99memstrack/memstrack.service
new file mode 100644
index 0000000..3717c73
--- /dev/null
+++ b/modules.d/99memstrack/memstrack.service
@@ -0,0 +1,15 @@
+[Unit]
+Description=Memstrack Anylazing Service
+DefaultDependencies=no
+Before=dracut-cmdline.service systemd-udevd.service local-fs-pre.target
+IgnoreOnIsolate=true
+ConditionKernelCommandLine=|rd.memdebug=4
+ConditionKernelCommandLine=|rd.memdebug=5
+
+[Service]
+Type=forking
+ExecStart=/bin/memstrack-start
+PIDFile=/run/memstrack.pid
+StandardInput=null
+StandardOutput=journal+console
+StandardError=journal+console
diff --git a/modules.d/99memstrack/module-setup.sh b/modules.d/99memstrack/module-setup.sh
new file mode 100755
index 0000000..27563eb
--- /dev/null
+++ b/modules.d/99memstrack/module-setup.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+check() {
+ if ! require_binaries pgrep pkill memstrack; then
+ dinfo "memstrack is not available"
+ dinfo "If you need to use rd.memdebug>=4, please install memstrack and procps-ng"
+ return 1
+ fi
+
+ return 0
+}
+
+depends() {
+ echo systemd
+ return 0
+}
+
+install() {
+ inst_multiple pgrep pkill nohup
+ inst "/bin/memstrack" "/bin/memstrack"
+
+ inst "$moddir/memstrack-start.sh" "/bin/memstrack-start"
+ inst_hook cleanup 99 "$moddir/memstrack-report.sh"
+
+ inst "$moddir/memstrack.service" "$systemdsystemunitdir/memstrack.service"
+
+ $SYSTEMCTL -q --root "$initdir" add-wants initrd.target memstrack.service
+}
diff --git a/modules.d/99shutdown/module-setup.sh b/modules.d/99shutdown/module-setup.sh
new file mode 100755
index 0000000..2b99902
--- /dev/null
+++ b/modules.d/99shutdown/module-setup.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ return 0
+}
+
+# called by dracut
+depends() {
+ echo base
+ return 0
+}
+
+# called by dracut
+install() {
+ local _d
+ inst_multiple umount poweroff reboot halt losetup stat sleep timeout
+ inst_multiple -o kexec
+ inst "$moddir/shutdown.sh" "$prefix/shutdown"
+ [ -e "${initdir}/lib" ] || mkdir -m 0755 -p "${initdir}"/lib
+ mkdir -m 0755 -p "${initdir}"/lib/dracut
+ mkdir -m 0755 -p "${initdir}"/lib/dracut/hooks
+ for _d in $hookdirs shutdown shutdown-emergency; do
+ mkdir -m 0755 -p "${initdir}"/lib/dracut/hooks/"$_d"
+ done
+}
diff --git a/modules.d/99shutdown/shutdown.sh b/modules.d/99shutdown/shutdown.sh
new file mode 100755
index 0000000..d611d44
--- /dev/null
+++ b/modules.d/99shutdown/shutdown.sh
@@ -0,0 +1,176 @@
+#!/bin/sh
+#
+# Licensed under the GPLv2
+#
+# Copyright 2011, Red Hat, Inc.
+# Harald Hoyer <harald@redhat.com>
+ACTION="$1"
+
+# Before trying to use /dev/console, verify that it exists,
+# and that it can actually be used. When console=null is used,
+# echo will fail. We do the check in a subshell, because otherwise
+# the process will be killed when when running as PID 1.
+# shellcheck disable=SC2217
+[ -w /dev/console ] \
+ && (echo < /dev/console > /dev/null 2> /dev/null) \
+ && exec < /dev/console >> /dev/console 2>> /dev/console
+
+export TERM=linux
+export PATH=/usr/sbin:/usr/bin:/sbin:/bin
+. /lib/dracut-lib.sh
+
+if [ "$(stat -c '%T' -f /)" = "tmpfs" ]; then
+ mount -o remount,rw /
+fi
+
+mkdir -p /oldsys
+for i in sys proc run dev; do
+ mkdir -p /oldsys/$i
+ mount --move /oldroot/$i /oldsys/$i
+done
+
+# if "kexec" was installed after creating the initramfs, we try to copy it from the real root
+# libz normally is pulled in via kmod/modprobe and udevadm
+if [ "$ACTION" = "kexec" ] && ! command -v kexec > /dev/null 2>&1; then
+ for p in /usr/sbin /usr/bin /sbin /bin; do
+ cp -a /oldroot/${p}/kexec $p > /dev/null 2>&1 && break
+ done
+ hash kexec
+fi
+
+trap "emergency_shell --shutdown shutdown Signal caught!" 0
+getarg 'rd.break=pre-shutdown' && emergency_shell --shutdown pre-shutdown "Break before pre-shutdown"
+
+source_hook pre-shutdown
+
+warn "Killing all remaining processes"
+
+killall_proc_mountpoint /oldroot || sleep 0.2
+
+# Timeout for umount calls. The value can be set to 0 to wait forever.
+_umount_timeout=$(getarg rd.shutdown.timeout.umount)
+_umount_timeout=${_umount_timeout:-90s}
+_timed_out_umounts=""
+
+umount_a() {
+ local _verbose="n"
+ if [ "$1" = "-v" ]; then
+ _verbose="y"
+ shift
+ exec 7>&2
+ else
+ exec 7> /dev/null
+ fi
+
+ local _did_umount="n"
+ while read -r _ mp _ || [ -n "$mp" ]; do
+ strstr "$mp" oldroot || continue
+ strstr "$_timed_out_umounts" " $mp " && continue
+
+ # Unmount the file system. The operation uses a timeout to avoid waiting
+ # indefinitely if this is e.g. a stuck NFS mount. The command is
+ # invoked in a subshell to silence also the "Killed" message that might
+ # be produced by the shell.
+ (
+ set +m
+ timeout --signal=KILL "$_umount_timeout" umount "$mp"
+ ) 2>&7
+ local ret=$?
+ if [ $ret -eq 0 ]; then
+ _did_umount="y"
+ warn "Unmounted $mp."
+ elif [ $ret -eq 137 ]; then
+ _timed_out_umounts="$_timed_out_umounts $mp "
+ warn "Unmounting $mp timed out."
+ elif [ "$_verbose" = "y" ]; then
+ warn "Unmounting $mp failed with status $ret."
+ fi
+ done < /proc/mounts
+
+ losetup -D 2>&7
+
+ exec 7>&-
+ [ "$_did_umount" = "y" ] && return 0
+ return 1
+}
+
+_cnt=0
+while [ $_cnt -le 40 ]; do
+ umount_a || break
+ _cnt=$((_cnt + 1))
+done
+
+[ $_cnt -ge 40 ] && umount_a -v
+
+if strstr "$(cat /proc/mounts)" "/oldroot"; then
+ warn "Cannot umount /oldroot"
+ for _pid in /proc/*; do
+ _pid=${_pid##/proc/}
+ case $_pid in
+ *[!0-9]*) continue ;;
+ esac
+ [ "$_pid" -eq $$ ] && continue
+
+ [ -e "/proc/$_pid/exe" ] || continue
+ [ -e "/proc/$_pid/root" ] || continue
+
+ if strstr "$(ls -l /proc/"$_pid" /proc/"$_pid"/fd 2> /dev/null)" "oldroot"; then
+ warn "Blocking umount of /oldroot [$_pid] $(cat /proc/"$_pid"/cmdline)"
+ else
+ warn "Still running [$_pid] $(cat /proc/"$_pid"/cmdline)"
+ fi
+
+ # shellcheck disable=SC2012
+ ls -l "/proc/$_pid/exe" 2>&1 | vwarn
+ # shellcheck disable=SC2012
+ ls -l "/proc/$_pid/fd" 2>&1 | vwarn
+ done
+fi
+
+_check_shutdown() {
+ local __f
+ local __s=0
+ for __f in "$hookdir"/shutdown/*.sh; do
+ [ -e "$__f" ] || continue
+ # shellcheck disable=SC1090 disable=SC2240
+ if (final="$1" . "$__f" "$1"); then
+ rm -f -- "$__f"
+ else
+ __s=1
+ fi
+ done
+ return $__s
+}
+
+_cnt=0
+while [ $_cnt -le 40 ]; do
+ _check_shutdown && break
+ _cnt=$((_cnt + 1))
+done
+[ $_cnt -ge 40 ] && _check_shutdown final
+
+if type plymouth > /dev/null 2>&1; then
+ plymouth --hide-splash
+elif [ -x /oldroot/bin/plymouth ]; then
+ /oldroot/bin/plymouth --hide-splash
+fi
+
+getarg 'rd.break=shutdown' && emergency_shell --shutdown shutdown "Break before shutdown"
+
+case "$ACTION" in
+ reboot | poweroff | halt)
+ $ACTION -f -n
+ warn "$ACTION failed!"
+ ;;
+ kexec)
+ kexec -e
+ warn "$ACTION failed!"
+ reboot -f -n
+ ;;
+ *)
+ warn "Shutdown called with argument '$ACTION'. Rebooting!"
+ reboot -f -n
+ ;;
+esac
+
+emergency_shell --shutdown shutdown
diff --git a/modules.d/99squash/init-squash.sh b/modules.d/99squash/init-squash.sh
new file mode 100755
index 0000000..59769f6
--- /dev/null
+++ b/modules.d/99squash/init-squash.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+PATH=/bin:/sbin
+
+[ -e /proc/self/mounts ] \
+ || (mkdir -p /proc && mount -t proc -o nosuid,noexec,nodev proc /proc)
+
+grep -q '^sysfs /sys sysfs' /proc/self/mounts \
+ || (mkdir -p /sys && mount -t sysfs -o nosuid,noexec,nodev sysfs /sys)
+
+grep -q '^devtmpfs /dev devtmpfs' /proc/self/mounts \
+ || (mkdir -p /dev && mount -t devtmpfs -o mode=755,noexec,nosuid,strictatime devtmpfs /dev)
+
+grep -q '^tmpfs /run tmpfs' /proc/self/mounts \
+ || (mkdir -p /run && mount -t tmpfs -o mode=755,noexec,nosuid,strictatime tmpfs /run)
+
+# Load required modules
+modprobe loop
+modprobe squashfs
+modprobe overlay
+
+# Mount the squash image
+mount -t ramfs ramfs /squash
+mkdir -p /squash/root /squash/overlay/upper /squash/overlay/work
+mount -t squashfs -o ro,loop /squash-root.img /squash/root
+
+# Setup new root overlay
+mkdir /newroot
+mount -t overlay overlay -o lowerdir=/squash/root,upperdir=/squash/overlay/upper,workdir=/squash/overlay/work/ /newroot/
+
+# Move all mount points to new root to prepare chroot
+mount --move /squash /newroot/squash
+
+# Jump to new root and clean setup files
+SYSTEMD_IN_INITRD=lenient exec switch_root /newroot /init
diff --git a/modules.d/99squash/module-setup.sh b/modules.d/99squash/module-setup.sh
new file mode 100755
index 0000000..dc2e0a2
--- /dev/null
+++ b/modules.d/99squash/module-setup.sh
@@ -0,0 +1,68 @@
+#!/bin/bash
+
+check() {
+ require_binaries mksquashfs unsquashfs || return 1
+ require_kernel_modules squashfs loop overlay || return 1
+
+ return 255
+}
+
+depends() {
+ echo "systemd-initrd"
+ return 0
+}
+
+installpost() {
+ local _busybox
+ _busybox=$(find_binary busybox)
+
+ # Move everything under $initdir except $squash_dir
+ # itself into squash image
+ for i in "$initdir"/*; do
+ [[ $squash_dir == "$i"/* ]] || mv "$i" "$squash_dir"/
+ done
+
+ # Create mount points for squash loader
+ 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
+ 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
+ for _i in sh echo mount modprobe mkdir switch_root grep umount; do
+ ln_r /usr/bin/busybox /usr/bin/$_i
+ done
+ else
+ DRACUT_RESOLVE_DEPS=1 inst_multiple sh mount modprobe mkdir switch_root grep umount
+
+ # libpthread workaround: pthread_cancel wants to dlopen libgcc_s.so
+ inst_libdir_file -o "libgcc_s.so*"
+
+ # FIPS workaround for Fedora/RHEL: libcrypto needs libssl when FIPS is enabled
+ [[ $DRACUT_FIPS_MODE ]] && inst_libdir_file -o "libssl.so*"
+ fi
+
+ hostonly="" instmods "loop" "squashfs" "overlay"
+ dracut_kernel_post
+
+ # Install squash image init script.
+ ln_r /usr/bin /bin
+ ln_r /usr/sbin /sbin
+ inst_simple "$moddir"/init-squash.sh /init
+
+ # make sure that library links are correct and up to date for squash loader
+ build_ld_cache
+}
+
+install() {
+ if [[ $DRACUT_SQUASH_POST_INST ]]; then
+ installpost
+ fi
+}
diff --git a/modules.d/99uefi-lib/module-setup.sh b/modules.d/99uefi-lib/module-setup.sh
new file mode 100755
index 0000000..6deeee8
--- /dev/null
+++ b/modules.d/99uefi-lib/module-setup.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+# called by dracut
+check() {
+ return 255
+}
+
+# called by dracut
+depends() {
+ echo bash
+ return 0
+}
+
+# called by dracut
+install() {
+ inst_simple "$moddir/uefi-lib.sh" "/lib/uefi-lib.sh"
+}
diff --git a/modules.d/99uefi-lib/uefi-lib.sh b/modules.d/99uefi-lib/uefi-lib.sh
new file mode 100755
index 0000000..06004ee
--- /dev/null
+++ b/modules.d/99uefi-lib/uefi-lib.sh
@@ -0,0 +1,162 @@
+#!/bin/bash
+#
+# Copyright 2013 Red Hat, Inc. All rights reserved.
+# Copyright 2013 Harald Hoyer <harald@redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+getbyte() {
+ local IFS= LC_CTYPE=C res c=0
+ read -r -n 1 -d '' c
+ res=$?
+ # the single quote in the argument of the printf
+ # yields the numeric value of $c (ASCII since LC_CTYPE=C)
+ [[ -n $c ]] && c=$(printf '%u' "'$c") || c=0
+ printf "%s" "$c"
+ return $res
+}
+
+getword() {
+ local b1=0 b2=0 val=0
+ b1=$(getbyte)
+ b2=$(getbyte)
+ ((val = b2 * 256 + b1))
+ echo "$val"
+ return 0
+}
+
+# E.g. Acpi(PNP0A08,0x0)/Pci(0x3,0x0)/Pci(0x0,0x0)/MAC(90E2BA265ED4,0x0)/Vlan(172)/Fibre(0x4EA06104A0CC0050,0x0)
+uefi_device_path() {
+ data=${1:-/sys/firmware/efi/efivars/FcoeBootDevice-a0ebca23-5f9c-447a-a268-22b6c158c2ac}
+ [ -f "$data" ] || return 1
+
+ local IFS= LC_CTYPE=C res tt len type hextype first
+ first=1
+ {
+ getword > /dev/null
+ getword > /dev/null
+ while :; do
+ type=$(getbyte) || return 1
+ subtype=$(getbyte) || return 1
+ len=$(getword) || return 1
+ hextype=$(printf "%02x%02x" "$type" "$subtype")
+ if [[ $first == 1 ]]; then
+ first=0
+ elif [[ $hextype != "7fff" ]]; then
+ printf "/"
+ fi
+ case $hextype in
+ 0101)
+ # PCI
+ tt=$(getword)
+ printf "PCI(0x%x,0x%x)" $((tt / 256)) $((tt & 255))
+ ;;
+ 0201)
+ # ACPI
+ printf "Acpi(0x%x,0x%x)" $(($(getword) + $(getword) * 65536)) $(($(getword) + $(getword) * 65536))
+ ;;
+ 0303)
+ # FIBRE
+ getword &> /dev/null
+ getword &> /dev/null
+ printf "Fibre(0x%x%x%x%x%x%x%x%x,0x%x)" \
+ "$(getbyte)" "$(getbyte)" "$(getbyte)" "$(getbyte)" \
+ "$(getbyte)" "$(getbyte)" "$(getbyte)" "$(getbyte)" \
+ "$(($(getword) + $(getword) * 65536 + 4294967296 * ($(getword) + $(getword) * 65536)))"
+ ;;
+ 030b)
+ # MAC
+ printf "MAC(%02x%02x%02x%02x%02x%02x," "$(getbyte)" "$(getbyte)" "$(getbyte)" "$(getbyte)" "$(getbyte)" "$(getbyte)"
+ for ((i = 0; i < 26; i++)); do tt=$(getbyte) || return 1; done
+ printf "0x%x)" "$(getbyte)"
+ ;;
+ 0314)
+ # VLAN
+ printf "VLAN(%d)" "$(getword)"
+ ;;
+ 7fff)
+ # END
+ printf "\n"
+ return 0
+ ;;
+ *)
+ #printf "Unknown(Type:0x%02x SubType:0x%02x len=%d)\n" "$type" "$subtype" "$len" >&2
+ for ((i = 0; i < len - 4; i++)); do tt=$(getbyte); done
+ ;;
+ esac
+ done
+ } < "$data"
+}
+
+get_fcoe_boot_mac() {
+ data=${1:-/sys/firmware/efi/efivars/FcoeBootDevice-a0ebca23-5f9c-447a-a268-22b6c158c2ac}
+ [ -f "$data" ] || return 1
+ local IFS= LC_CTYPE=C tt len type hextype
+ {
+ getword > /dev/null
+ getword > /dev/null
+ while :; do
+ type=$(getbyte) || return 1
+ subtype=$(getbyte) || return 1
+ len=$(getword) || return 1
+ hextype=$(printf "%02x%02x" "$type" "$subtype")
+ case $hextype in
+ 030b)
+ # MAC
+ printf "%02x:%02x:%02x:%02x:%02x:%02x" "$(getbyte)" "$(getbyte)" "$(getbyte)" "$(getbyte)" "$(getbyte)" "$(getbyte)"
+ for ((i = 0; i < 27; i++)); do tt=$(getbyte) || return 1; done
+ ;;
+ 7fff)
+ # END
+ return 0
+ ;;
+ *)
+ #printf "Unknown(Type:0x%02x SubType:0x%02x len=%d)\n" "$type" "$subtype" "$len" >&2
+ for ((i = 0; i < len - 4; i++)); do tt=$(getbyte); done
+ ;;
+ esac
+ done
+ } < "$data"
+}
+
+get_fcoe_boot_vlan() {
+ data=${1:-/sys/firmware/efi/efivars/FcoeBootDevice-a0ebca23-5f9c-447a-a268-22b6c158c2ac}
+ [ -f "$data" ] || return 1
+ local IFS= LC_CTYPE=C tt len type hextype
+ {
+ getword > /dev/null
+ getword > /dev/null
+ while :; do
+ type=$(getbyte) || return 1
+ subtype=$(getbyte) || return 1
+ len=$(getword) || return 1
+ hextype=$(printf "%02x%02x" "$type" "$subtype")
+ case $hextype in
+ 0314)
+ # VLAN
+ printf "%d" "$(getword)"
+ ;;
+ 7fff)
+ # END
+ return 0
+ ;;
+ *)
+ #printf "Unknown(Type:0x%02x SubType:0x%02x len=%d)\n" "$type" "$subtype" "$len" >&2
+ for ((i = 0; i < len; i++)); do tt=$(getbyte); done
+ ;;
+ esac
+ done
+ } < "$data"
+}