#!/bin/sh

alterator_api_version=1

. alterator-sh-functions
. shell-config
. grub-raid-boot
. grub-disk
. grub-bootable
. grub-md-list

# effects grub menu l18n
if [ -n "$in_language" ]; then
	LANG="$in_language"
else
	if [ -s /etc/sysconfig/i18n ]; then
		. /etc/sysconfig/i18n
	fi
fi

export LANG

efi_dir="/boot/efi"

pwconf=/etc/grub.d/50_password

gruboutput=

make_gruboutput() {
	gruboutput=`mktemp --tmpdir grub.XXXXXXXXXX` \
		|| (write_error "$(_ "Can't create tempfile ")$gruboutput!"; return 1)
	if [ -z "$gruboutput" ] || [ ! -e "$gruboutput" ]; then
		write_error "$(_ "Can't create tempfile ")$gruboutput!"
		return 1
	fi
}

make_grubcfg() {
	if ! grub-mkconfig -o /boot/grub/grub.cfg > $gruboutput 2>&1; then
		write_error "Can't create grub menu :`cat $gruboutput`"
		return 1
	fi
	[ -f /_NEW_SYSTEM_ ] && cp -ab $gruboutput /tmp/grub.log ||:
}

write_efi() {
	make_gruboutput || return 1

	if ! grub-install --uefi-secure-boot --recheck >> $gruboutput 2>&1; then
		write_error "$(_ "Can't install grub into $efi_dir: ")`cat $gruboutput`"
		return 1
	fi

	make_grubcfg
}

change_passwd() {
	case "$in_passwd" in
	"#f")
		del_passwd;;
	"#t")
		check_passwds;;
	*)
		write_error "`_ "Internal error"`";;
	esac
}

check_passwds() {
	if [ -z "$in_passwd_1" -a -z "$in_passwd_2" ]; then
		write_error "`_ "You should define a password for boot with options"`"
	elif [ "$in_passwd_1" != "$in_passwd_2" ]; then
		write_error "`_ "Passwords mismatch"`"
	else
		set_passwd
	fi
}

hash_passwd() {
	echo -e "$in_passwd_1\n$in_passwd_1" \
	| LANG=C grub-mkpasswd-pbkdf2 \
	| sed -rn 's,^.* (grub\.pbkdf2.*)$,\1,p'
}

set_passwd() {
	install -pm700 /dev/null $pwconf
	cat > $pwconf <<-EOF_CONF
	#!/bin/sh
	cat << EOF
	set superusers="boot"
	password_pbkdf2 boot `hash_passwd`
	EOF
	EOF_CONF
	grub-mkconfig -o /boot/grub/grub.cfg
}

del_passwd() {
	shred -u $pwconf
}

read_passwd_status() {
	if [ "$DURING_INSTALL" == "1" ]; then
		write_bool_param 'passwd' 'yes'
        else
	[ -s $pwconf ] &&
		write_bool_param 'passwd' 'yes' ||
		write_bool_param 'passwd' 'no'
        fi
}

list_devices() {
	if [ -d "/sys/firmware/efi" -a -d "$efi_dir" ]; then
		write_enum_item "efi" "$(_ "EFI")"
	fi
	list_bootloader_places
	write_enum_item "none" "$(_ "Skip bootloader install")"
}

write_device() {
	make_gruboutput || return 1

	# fallback: BIOS bootloader installation when booted in EFI mode
	if [ -d "/sys/firmware/efi" ]; then
		grep -q efivars /etc/modules || echo efivars >> /etc/modules
		target="--target=i386-pc"
	fi

	bootdev="`readlink -e $1`"
	if [ -z "$bootdev" ]; then
		write_error "$(_ "No device for install given!")"
		return 1
	fi
	raid_members=$(grub_md_list "${bootdev#/dev/}" 2>/dev/null)
	[ -z "$raid_members" ] || bootdev=$raid_members
	#tout=`mktemp`
	GRUB_FORCE="no"
	GRUB_DEV=
	for dev in $bootdev; do
		GRUB_DEV="$(blockdev_get_symlink "$dev") $GRUB_DEV"
		grub-install $target "$dev" >> $gruboutput 2>&1
		if [ $? -ne 0 ]; then
			if grep blocklists $gruboutput; then
				GRUB_FORCE="yes"
				grub-install $target "$dev" --force >> $gruboutput 2>&1
				if [ $? -ne 0 ]; then
					write_error "$(_ "Can't install grub on ")$dev$(_ " even using blocklists :")`cat $gruboutput`"
					return 1
				fi
			else
				write_error "$(_ "Can't install grub on ")$dev :`cat $gruboutput`"
				return 1
			fi
		fi
		set_bootable_flag "$dev"
	done
	if ! grep "^GRUB_AUTOUPDATE_DEVICE=" /etc/sysconfig/grub2 > /dev/null 2>&1; then
		echo "GRUB_AUTOUPDATE_DEVICE='$GRUB_DEV'" >> /etc/sysconfig/grub2
	else
		sed -i "s|GRUB_AUTOUPDATE_DEVICE=.*|GRUB_AUTOUPDATE_DEVICE='$GRUB_DEV'|" /etc/sysconfig/grub2
	fi
	if ! grep "^GRUB_AUTOUPDATE_FORCE=" /etc/sysconfig/grub2 > /dev/null 2>&1; then
		echo "GRUB_AUTOUPDATE_FORCE='$GRUB_FORCE'" >> /etc/sysconfig/grub2
	else
		sed -i "s|GRUB_AUTOUPDATE_FORCE=.*|GRUB_AUTOUPDATE_FORCE='$GRUB_FORCE'|" /etc/sysconfig/grub2
	fi

	make_grubcfg
}

on_message() {
	case "$in_action" in
	list)
		case "$in__objects" in
		"devices") list_devices;;
		esac
		;;
	read)
		case "$in__objects" in
		"passwd") read_passwd_status;;
		esac
		;;
	write)
		change_passwd
		case "$in_device" in
		"none")
			;;
		"efi")
			write_efi
			;;
		*)
			write_device "$in_device" "$in_runhooks"
			;;
		esac
	esac
}

message_loop
