1#!/bin/sh
2# shellcheck disable=SC2034,SC2154
3
4. /lib/dracut-zfs-lib.sh
5
6decode_root_args || return 0
7
8GENERATOR_FILE=/run/systemd/generator/sysroot.mount
9GENERATOR_EXTENSION=/run/systemd/generator/sysroot.mount.d/zfs-enhancement.conf
10
11if [ -e "$GENERATOR_FILE" ] && [ -e "$GENERATOR_EXTENSION" ]; then
12	# We're under systemd and dracut-zfs-generator ran to completion.
13	info "ZFS: Delegating root mount to sysroot.mount at al."
14
15	# We now prevent Dracut from running this thing again.
16	rm -f "$hookdir"/mount/*zfs*
17	return
18fi
19
20info "ZFS: No sysroot.mount exists or zfs-generator did not extend it."
21info "ZFS: Mounting root with the traditional mount-zfs.sh instead."
22
23# ask_for_password tries prompt cmd
24#
25# Wraps around plymouth ask-for-password and adds fallback to tty password ask
26# if plymouth is not present.
27ask_for_password() {
28    tries="$1"
29    prompt="$2"
30    cmd="$3"
31
32    {
33        flock -s 9
34
35        # Prompt for password with plymouth, if installed and running.
36        if plymouth --ping 2>/dev/null; then
37            plymouth ask-for-password \
38                --prompt "$prompt" --number-of-tries="$tries" | \
39                eval "$cmd"
40            ret=$?
41        else
42            i=1
43            while [ "$i" -le "$tries" ]; do
44                printf "%s [%i/%i]:" "$prompt" "$i" "$tries" >&2
45                eval "$cmd" && ret=0 && break
46                ret=$?
47                i=$((i+1))
48                printf '\n' >&2
49            done
50            unset i
51        fi
52    } 9>/.console_lock
53
54    [ "$ret" -ne 0 ] && echo "Wrong password" >&2
55    return "$ret"
56}
57
58
59# Delay until all required block devices are present.
60modprobe zfs 2>/dev/null
61udevadm settle
62
63ZFS_DATASET=
64ZFS_POOL=
65
66if [ "${root}" = "zfs:AUTO" ] ; then
67	if ! ZFS_DATASET="$(zpool get -Ho value bootfs | grep -m1 -vFx -)"; then
68		# shellcheck disable=SC2086
69		zpool import -N -a ${ZPOOL_IMPORT_OPTS}
70		if ! ZFS_DATASET="$(zpool get -Ho value bootfs | grep -m1 -vFx -)"; then
71			warn "ZFS: No bootfs attribute found in importable pools."
72			zpool export -aF
73
74			rootok=0
75			return 1
76		fi
77	fi
78	info "ZFS: Using ${ZFS_DATASET} as root."
79fi
80
81ZFS_DATASET="${ZFS_DATASET:-${root}}"
82ZFS_POOL="${ZFS_DATASET%%/*}"
83
84
85if ! zpool get -Ho value name "${ZFS_POOL}" > /dev/null 2>&1; then
86    info "ZFS: Importing pool ${ZFS_POOL}..."
87    # shellcheck disable=SC2086
88    if ! zpool import -N ${ZPOOL_IMPORT_OPTS} "${ZFS_POOL}"; then
89        warn "ZFS: Unable to import pool ${ZFS_POOL}"
90        rootok=0
91        return 1
92    fi
93fi
94
95# Load keys if we can or if we need to
96# TODO: for_relevant_root_children like in zfs-load-key.sh.in
97if [ "$(zpool get -Ho value feature@encryption "${ZFS_POOL}")" = 'active' ]; then
98	# if the root dataset has encryption enabled
99	ENCRYPTIONROOT="$(zfs get -Ho value encryptionroot "${ZFS_DATASET}")"
100	if ! [ "${ENCRYPTIONROOT}" = "-" ]; then
101		KEYSTATUS="$(zfs get -Ho value keystatus "${ENCRYPTIONROOT}")"
102		# if the key needs to be loaded
103		if [ "$KEYSTATUS" = "unavailable" ]; then
104			# decrypt them
105			ask_for_password \
106				5 \
107				"Encrypted ZFS password for ${ENCRYPTIONROOT}: " \
108				"zfs load-key '${ENCRYPTIONROOT}'"
109		fi
110	fi
111fi
112
113# Let us tell the initrd to run on shutdown.
114# We have a shutdown hook to run
115# because we imported the pool.
116info "ZFS: Mounting dataset ${ZFS_DATASET}..."
117if ! mount_dataset "${ZFS_DATASET}"; then
118  rootok=0
119  return 1
120fi
121