#!/usr/bin/awk -f

# Accepts a newline-separated list of kernel cmdline words. Suggested usage:
# > cat /proc/cmdline | xargs printf "%s\n" | zfs-parse-cmdline
#
# Interprets special forms of `root=` kernel cmdline parameter:
# - `root=zfs`: import all pools (`ZFS_ROOT_MODE=all`)
# - `root=zfs:<POOL>`: import <POOL> and use bootfs property (`ZFS_ROOT_MODE=pool`)
# - `root=zfs:<POOL>/<DATASET>`: import <POOL> and use <DATASET> (`ZFS_ROOT_MODE=dataset`)
#
# Alternatively, `zfsroot=` parameter may be used with the equivalent semantics.
# This is supported to avoid inhibiting systemd-gpt-auto-generator (which might
# be useful e.g. to auto-configure LUKS decryption).
#
# Additionally, interprets `zfsalt=` kernel cmdline parameter:
# - `zfsalt=ignore`: ignore (do not mount) other OS roots
# - `zfsalt=/path`: mount other OS roots under `/path/(id)`
#
# "Other OS roots" are defined as datasets which have a different value of the
# `dev.zfsboot:machine-id` property than the bootfs.

# Returns a set of KEY=val assignments
# - ZFS_ROOT_MODE: "dataset", "pool", "all", "none"
#   - all: import all pools, use the first one with a bootfs property
#   - pool: import a specific pool, use bootfs to determine the dataset
#   - dataset: import a specific pool, use a specific dataset
#   - none: not using zfs for root
# - ZFS_ROOT_POOL: contains the root pool name (used with mode "dataset" and "pool")
# - ZFS_ROOT_DATASET: contains the root dataset name (used with mode "dataset")
# - ZFS_ROOT_ALT_PREFIX: contains the mountpoint prefix for other OS roots
#                        (empty if "ignore")

$0 ~ /^root=/ {
	root = substr($0, 6)
}

$0 ~ /^zfsroot=/ {
	root = substr($0, 9)
}

$0 ~ /^zfsalt=/ {
	alt = substr($0, 8)
}

END {
	if (root == "zfs") {
		# import all pools
		zfs_root_mode = "all"
	} else if (match(root, /^zfs[:=][^\/]+$/)) {
		root = substr(root, 5)
		# import a specific pool
		zfs_root_mode = "pool"
		zfs_root_pool = root
	} else if (match(root, /^zfs[:=][^\/]+(\/[^\/]+)+$/)) {
		root = substr(root, 5)
		# use a particular dataset
		zfs_root_mode = "dataset"
		zfs_root_dataset = root
		split(root, items, "/")
		zfs_root_pool = items[1]
	} else {
		zfs_root_mode = "none"
	}

	if (alt && alt != "ignore") {
		zfs_alt = alt
	}

	printf "ZFS_ROOT_MODE=%s\n", zfs_root_mode
	if (zfs_root_pool) {
		printf "ZFS_ROOT_POOL=%s\n", zfs_root_pool
	}
	if (zfs_root_dataset) {
		printf "ZFS_ROOT_DATASET=%s\n", zfs_root_dataset
	}
	printf "ZFS_ROOT_ALT_PREFIX=%s\n", zfs_alt
}

# vim: ft=awk ts=8 noet:
