#!/usr/bin/env bash
###########################################################
# This script generates a memtest86plus entry on grub.cfg #
# if memtest is installed on the system.                  #
###########################################################

prefix="/usr"
exec_prefix="${prefix}"

datarootdir="/usr/share"
datadir="${datarootdir}"

export OLD_TEXTDOMAIN="$TEXTDOMAIN"

export TEXTDOMAIN=memtest-grub

. "${datadir}/grub/grub-mkconfig_lib"

MEMTEST86_IMAGE_64="/boot/memtest86plus/memtest64"
MEMTEST86_IMAGE_32="/boot/memtest86plus/memtest32"
CLASS="--class memtest86 --class gnu --class tool"

MEMTEST_TITLE="$(gettext_printf "Memory Test")"
TGT=

case "$(uname -m)" in
	# Kernel modifies utsname->machine[1] on the fly.
	# arch/x86/kernel/cpu/common.c arch_cpu_finalize_init()
	i486)
		# Memtest86+ requires at least i586.
		exit 0
		;;
	i?86)
		# Load 32-bit binary for Afterglow.
		TGT=afterglow
		;;
	*)
		# Load 64-bit binary regardless of the platform
		# (except 32-bit EFI).
		TGT=mainline
		;;
esac

generate_mainline() {
	if [ -e "${MEMTEST86_IMAGE_64}" ] && \
	   is_path_readable_by_grub "${MEMTEST86_IMAGE_64}" ; then
		## image exists, create menu entry
		echo "$(gettext_printf "Found Memtest86+ image: %s" "${MEMTEST86_IMAGE_64}")" >&2
		_GRUB_MEMTEST_HINTS_STRING="$(${grub_probe} --target=hints_string ${MEMTEST86_IMAGE_64} 2>/dev/null)"
		_GRUB_MEMTEST_FS_UUID="$(${grub_probe} --target=fs_uuid ${MEMTEST86_IMAGE_64} 2>/dev/null)"
		_GRUB_MEMTEST_REL_PATH="$(make_system_path_relative_to_its_root ${MEMTEST86_IMAGE_64} 2>/dev/null)"
		# The binary can be booted from both BIOS and EFI.
		# We load the x64 binary for i386-pc, x86_64-efi and loongarch64-efi.
		# (There is no such thing as x86_64-pc.)
		# Only load memtest32 for 32-bit EFI.
		cat << EOF
if [ "\${grub_cpu}" == "x86_64" -o "\${grub_cpu}" == "loongarch64" -o "\${grub_platform}" == "pc" ]; then
	menuentry '$MEMTEST_TITLE' ${CLASS} {
		if loadfont unicode ; then
			set gfxmode=1024x768,800x600,auto
			set gfxpayload=800x600,1024x768
			terminal_output gfxterm
		fi
		search --fs-uuid --no-floppy --set=root ${_GRUB_MEMTEST_HINTS_STRING} ${_GRUB_MEMTEST_FS_UUID}
		linux ${_GRUB_MEMTEST_REL_PATH} ${GRUB_CMDLINE_MEMTEST86}
	}
EOF
	fi
	
	if [ -e "${MEMTEST86_IMAGE_32}" ] && \
	   is_path_readable_by_grub "${MEMTEST86_IMAGE_32}" ; then
		## image exists, create menu entry
		echo "$(gettext_printf "Found Memtest86+ image: %s" "${MEMTEST86_IMAGE_32}")" >&2
		_GRUB_MEMTEST_HINTS_STRING="$(${grub_probe} --target=hints_string ${MEMTEST86_IMAGE_32} 2>/dev/null)"
		_GRUB_MEMTEST_FS_UUID="$(${grub_probe} --target=fs_uuid ${MEMTEST86_IMAGE_32} 2>/dev/null)"
		_GRUB_MEMTEST_REL_PATH="$(make_system_path_relative_to_its_root ${MEMTEST86_IMAGE_32} 2>/dev/null)"
		cat << EOF
elif [ "\${grub_cpu}-\${grub_platform}" == "i386-efi" ] ; then
	menuentry '$MEMTEST_TITLE' ${CLASS} {
		if loadfont unicode ; then
			set gfxmode=1024x768,800x600,auto
			set gfxpayload=800x600,1024x768
			terminal_output gfxterm
		fi
		search --fs-uuid --no-floppy --set=root ${_GRUB_MEMTEST_HINTS_STRING} ${_GRUB_MEMTEST_FS_UUID}
		linux ${_GRUB_MEMTEST_REL_PATH} ${GRUB_CMDLINE_MEMTEST86}
	}
EOF
	fi
	# Terminate the if block	
	cat << EOF
fi
EOF
}

generate_afterglow() {
	if [ -e "${MEMTEST86_IMAGE_32}" ] && \
	   is_path_readable_by_grub "${MEMTEST86_IMAGE_32}" ; then
		## image exists, create menu entry
		echo "$(gettext_printf "Found Memtest86+ image: %s" "${MEMTEST86_IMAGE_32}")" >&2
		_GRUB_MEMTEST_HINTS_STRING="$(${grub_probe} --target=hints_string ${MEMTEST86_IMAGE_32} 2>/dev/null)"
		_GRUB_MEMTEST_FS_UUID="$(${grub_probe} --target=fs_uuid ${MEMTEST86_IMAGE_32} 2>/dev/null)"
		_GRUB_MEMTEST_REL_PATH="$(make_system_path_relative_to_its_root ${MEMTEST86_IMAGE_32} 2>/dev/null)"
		cat << EOF
menuentry '$MEMTEST_TITLE' ${CLASS} {
	if loadfont unicode ; then
		set gfxmode=1024x768,800x600,auto
		set gfxpayload=800x600,1024x768
		terminal_output gfxterm
	fi
	search --fs-uuid --no-floppy --set=root ${_GRUB_MEMTEST_HINTS_STRING} ${_GRUB_MEMTEST_FS_UUID}
	linux ${_GRUB_MEMTEST_REL_PATH} ${GRUB_CMDLINE_MEMTEST86}
}
EOF
	fi
}

case "$TGT" in
	mainline)
		generate_mainline
		;;
	afterglow)
		generate_afterglow
		;;
esac

export TEXTDOMAIN="$OLD_TEXTDOMAIN"
