#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh

# This script generates a service that manages a dm-verity device for the chosen ROOT partition


set -e

cmdline=( $(</proc/cmdline) )

# Usage: cmdline_arg name default_value
cmdline_arg() {
    local name="$1" value="$2"
    for arg in "${cmdline[@]}"; do
	if [[ "${arg%%=*}" == "${name}" ]]; then
	    value="${arg#*=}"
	fi
    done
    echo "${value}"
}

UNIT_DIR="${1:-/tmp}"

root=$(cmdline_arg verity.root)
roothash=$(cmdline_arg verity.roothash)
hashoffset=$(cmdline_arg verity.hashoffset)

case "${root}" in
    LABEL=*)
	root="$(echo $root | sed 's,/,\\x2f,g')"
	root="/dev/disk/by-label/${root#LABEL=}"
	;;
    UUID=*)
	root="${root#UUID=}"
	root="/dev/disk/by-uuid/${root,,}"
	;;
    PARTUUID=*)
	root="${root#PARTUUID=}"
	root="/dev/disk/by-partuuid/${root,,}"
	;;
    PARTLABEL=*)
	root="/dev/disk/by-partlabel/${root#PARTLABEL=}"
	;;
esac

# Only proceed if the source is a path.
if [[ "${root}" != /* ]]; then
    exit 0
fi

# Only generate the service if we have sufficient parameters.
if [[ -n "${root}" && -n "${roothash}" ]]; then
    device=$(systemd-escape --suffix=device --path "${root}")

    cat >"${UNIT_DIR}/verity-setup.service" <<-EOF
	# Automatically generated by verity-generator

	[Unit]
	Description=Verity Setup for /dev/mapper/root
	SourcePath=/proc/cmdline
	DefaultDependencies=no
	IgnoreOnIsolate=true
	BindsTo=dev-mapper-root.device
	BindsTo=${device}
	After=${device}

	[Service]
	Type=oneshot
	RemainAfterExit=yes
	ExecStart=/bin/sh -c '/sbin/veritysetup create root ${hashoffset:+--hash-offset="${hashoffset}"} "${root}" "${root}" "${roothash}"'
	ExecStop=/sbin/veritysetup remove root
EOF

    requires_dir="${UNIT_DIR}/dev-mapper-root.device.requires"
    mkdir -p "${requires_dir}"
    ln -sf "../verity-setup.service" "${requires_dir}/verity-setup.service"
fi