#!/bin/sh -eu

. shell-error
. shell-args

PROJECT=bootloader

MIBOOT_DIR="/lib/$PROJECT"
KERNEL_DIR="$MIBOOT_DIR"

show_help()
{
	cat <<-EOF
	Usage: $PROG [options]

	Options:
	  -b, --bootdir=DIR   specifies boot directory (default: /boot);
	  -q, --quiet         try to be more quiet;
	  -v, --verbose       print a message for each action;
	  -V, --version       print program version and exit;
	  -h, --help          show this text and exit.

	Report bugs to authors.

	EOF
	exit
}

print_version()
{
	cat <<-EOF
	$PROG version 1.0.0
	Written by Alexey Gladkov.

	Copyright (C) 2020  Alexey Gladkov <gladkov.alexey@gmail.com>
	This is free software; see the source for copying conditions.  There is NO
	warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
	EOF
	exit
}

bootloader_build_image()
{
	verbose "Building bootloader runtime image"

	export KERNEL="$(cat "$KERNEL_DIR/boot/version")"
	export KERNEL_CONFIG="$KERNEL_DIR/boot/config"
	export KERNEL_MODULES_DIR="/lib/modules/$KERNEL"

	make-initrd -k "$KERNEL" -b "$KERNEL_DIR/boot" -c "/etc/$PROJECT.mk"
}

bootloader_copy()
{
	! cmp -s -- "$@" ||
		return 0
	mkdir $verbose -p -- "$bootdir/efi/EFI/LINUX"
	cp $verbose -f -- "$@"
}

bootloader_update_config()
{
	verbose "Updating bootloader configuration"

	. shell-git-config

	conf="$bootdir/$PROJECT.conf"

	if [ ! -f "$conf" ]; then
		root="$(findmnt -n -o UUID -T "$bootdir")"

		{
			printf '[global]\n'
			printf '\t%s\n' \
				"timeout = 10" \
				"cmdline = ro root=UUID=$root"
		} > "$conf"
	fi

	labels=' '

	git_config_get_subsections_handler()
	{
		labels="$labels\"$1\" "
	}

	print_entry()
	{
		local kver label kernel initrd initrd_name suf
		for kernel; do
			[ -f "$kernel" ] ||
				return 0

			kver="${kernel##*/vmlinuz}"
			kver="${kver#-}"

			label="${kver:+Kernel ($kver)}"
			label="${label:-Default}"

			if [ -z "${labels##* \"$label\" *}" ]; then
				verbose "Skip $label"
				continue
			fi

			initrd=
			for initrd_name in initrd initramfs; do
				for suf in '' '.img'; do
					if [ -f "$bootdir/$initrd_name${kver:+-$kver}$suf" ]; then
						initrd="$bootdir/$initrd_name${kver:+-$kver}$suf"
						break 2
					fi
				done
			done

			verbose "Adding new entry for '$label'"

			{
				printf '\n'
				printf '[boot "%s"]\n' "$label"
				printf '\tkernel = %s\n' "$kernel"
				[ -z "$initrd" ] ||
					printf '\tinitrd = %s\n' "$initrd"
			}
		done
	}

	git_config_env "$conf"
	git_config_get_subsections 'boot'

	{
		print_entry "$bootdir"/vmlinuz
		print_entry "$bootdir"/vmlinuz-[A-Za-z]*
		print_entry "$bootdir"/vmlinuz-[0-9]*
	} >> "$conf"
}

TEMP=`getopt -n "$PROG" -o "b:,$getopt_common_opts" -l "boot:,$getopt_common_longopts" -- "$@"` ||
	show_usage
eval set -- "$TEMP"

bootdir=/boot

while :; do
	case "$1" in
		-b|--boot-dir)
			bootdir="$(opt_check_dir "$1" "$2")"
			;;
		-h|--help) show_help
			;;
		-q|--quiet) quiet=-q; verbose=
			;;
		-v|--verbose) verbose=-v; quiet=
			;;
		-V|--version) print_version "$PROG"
			;;
		--) shift; break
			;;
	esac
	shift
done

bootloader_build_image

bootloader_copy "$KERNEL_DIR/boot/vmlinuz"        "$bootdir/efi/EFI/LINUX/$PROJECT.efi"
bootloader_copy "$KERNEL_DIR/boot/bootloader.img" "$bootdir/efi/EFI/LINUX/$PROJECT.img"

bootloader_update_config
