#!/bin/sh
#
# Copyright (c) 2020, The ULBSD Project
# Copyright (c) 2020, The NomadBSD Project
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
#   list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
#   this list of conditions and the following disclaimer in the documentation
#   and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# $Id: initgfx 38 2020-07-28 23:22:59Z sv $
#
# PROVIDE: initgfx
# REQUIRE: FILESYSTEMS NETWORKING
# BEFORE: sddm

. /etc/rc.subr

name=initgfx
start_cmd="do_initgfx"

rcvar=initgfx_enable

load_rc_config $name

: ${initgfx_enable:="NO"}
: ${initgfx_menu:="NO"}

path_ati_cfg="/usr/local/etc/X11/xorg.conf.d/20-ati.conf"
path_amd_cfg="/usr/local/etc/X11/xorg.conf.d/20-amdgpu.conf"
path_intel_cfg="/usr/local/etc/X11/xorg.conf.d/10-intel.conf"
path_vesa_cfg="/usr/local/etc/X11/xorg.conf.d/10-vesa.conf"
path_scfb_cfg="/usr/local/etc/X11/xorg.conf.d/10-scfb.conf"
path_vmware_cfg="/usr/local/etc/X11/xorg.conf.d/10-vmware.conf"
path_nvidia_cfg="/usr/local/etc/X11/xorg.conf.d/10-nvidia.conf"

path_drm_legacy="/usr/local/share/ulbsd/drivers/drm_legacy"
path_nvidia="/usr/local/share/ulbsd/drivers/nvidia"
nvidia_drivers="440 390 340 304"

initgfx_autodetect=0
initgfx_use_vesa=0
initgfx_use_scfb=0

gfx_menu()
{
	local ret="/tmp/gfx_menu.ret"
	local lang driver msg hline opts efiboot
	if sysctl machdep.bootmethod | grep -q BIOS; then
		efiboot=0
		driver="VESA"
	else
		efiboot=1
		driver="SCFB"
	fi

	if [ "${sddm_lang}" == "ru_RU" ]
	then
	    lang="ru_RU"
	else
	    lang="en_US"
	fi

	if [ "${lang}" == "ru_RU" ]
	then
		title="Драйвер графического режима"
		msg="Если при автоматическом определении драйвера графического"
		msg="${msg} режима возникают проблемы, то вы можете выбрать драйвер"
		msg="${msg} ${driver}. Драйвер ${driver} не поддерживает аппаратное ускорение"
		msg="${msg} графики, но работает на большинстве систем."
		hline="Используйте ↑↓ и ENTER для выбора"
		opts="Autodetect:Автоматическое определение драйвера"
		if [ ${efiboot} -eq 1 ]; then
			opts="${opts}:SCFB:Универсальный драйвер"
		else
			opts="${opts}:VESA:Универсальный драйвер"
		fi
	else
		title="Graphics mode driver"
		msg="If you have problems with the automatic detection of the"
		msg="${msg} graphics driver, you can select the ${driver} driver."
		msg="${msg} The ${driver} driver does not support hardware graphics"
		msg="${msg} acceleration, but it works on most systems."
		hline="Use ↑↓ and ENTER for choice"
		opts="Autodetect:Autodetect graphics driver"
		if [ ${efiboot} -eq 1 ]; then
			opts="${opts}:SCFB:Generic video driver"
		else
			opts="${opts}:VESA:Generic video driver"
		fi
	fi

	while [ true ]; do
		local IFS=:
                TERM=xterm env LANG="${lang}.UTF-8" /usr/local/bin/cdialog --title "${title}" --hline "${hline}" --no-collapse --no-cancel --menu "${msg}" 12 62 2 ${opts} 2>${ret}
		[ $? -ne 0 ] && continue
		opt=$(cat ${ret})
		rm -f ${ret}
		case ${opt} in
			Autodetect)
				initgfx_autodetect=1
				;;
			SCFB)
				initgfx_use_scfb=1
				;;
			VESA)
				initgfx_use_vesa=1
				;;
		esac
		return
	done
}

do_initgfx()
{
	local path_generic_cfg i l driver
	
	rm -f ${path_ati_cfg}
	sysrc kld_list-=/boot/modules/radeonkms.ko >/dev/null

	rm -f ${path_amd_cfg}
	sysrc  kld_list-=/boot/modules/amdgpu.ko >/dev/null

	rm -f ${path_intel_cfg}
	sysrc  kld_list-="${path_drm_legacy}/boot/modules/i915kms.ko" >/dev/null
	sysrc  kld_list-=/boot/modules/i915kms.ko >/dev/null

	rm -f ${path_vesa_cfg}
	rm -f ${path_scfb_cfg}
	rm -f ${path_vmware_cfg}

	rm -f ${path_nvidia_cfg}
	for i in ${nvidia_drivers}; do
		sysrc kld_list-="${path_nvidia}/${i}/boot/modules/nvidia.ko" >/dev/null
		sysrc kld_list-="${path_nvidia}/${i}/boot/modules/nvidia-modeset.ko" >/dev/null
		for l in $(ls ${path_nvidia}/${i}/usr/local/lib/vdpau/); do
			rm -f /usr/local/lib/vdpau/$l
		done
	done
	rm -f /usr/local/etc/libmap.d/nvidia.conf
	rm -f /usr/local/libdata/ldconfig/nvidia-driver

	# In VirtualBox we are done here
	pciconf -lv | grep -B3 display | grep -q -i virtualbox && return

	# Do not show menu if syscons is disabled or initgfx_menu="NO"
	syscons_disabled=$(kenv | awk -F '["=]+' '
		/hw.syscons.disable/ { print $2 }')
	if [ ${syscons_disabled:=0} -eq 0 ]; then
		sysons_disabled=$(sysctl -n hw.syscons.disable 2>/dev/null)
	fi
	if checkyesno initgfx_menu; then
		if [ ${syscons_disabled:=0} -eq 0 ]; then
			gfx_menu
		else
			initgfx_autodetect=1
		fi
	elif [ -n "${initgfx_default}" ]; then
		case ${initgfx_default} in
		vesa|scfb)
			initgfx_autodetect=0
			;;
		*)
			echo "Error: Unknown driver ${initgfx_default}. " \
				 "Use scfb or vesa" >&2
			initgfx_autodetect=1
			;;
		esac
	else
		initgfx_autodetect=1
	fi
	if [ ${initgfx_autodetect} -eq 1 ]; then
		for i in vmware nvidia intel ati-amd; do
			/usr/local/share/ulbsd/scripts/ulbsd-gfx-${i} && return
		done
	fi
	if [ ${initgfx_use_vesa} -eq 1 ]; then
		driver="vesa"
	elif [ ${initgfx_use_scfb} -eq 1 ]; then
		driver="scfb"
	elif [ -n "${initgfx_default}" ]; then
		driver=${initgfx_default}
	fi
	echo "${driver}" > /var/run/gfxdriver
	unit=$(sysctl -n hw.pci.default_vgapci_unit)
	[ -z "$unit" -o "$unit" =  "-1" ] && unit=0
	busID=$(pciconf -lv | grep ^vgapci${unit} | head -1 | \
		sed -E 's/^vgapci[0-9]@pci[0-9]:([0-9:]+):.*$/\1/')
	eval path_generic_cfg=\${path_${driver}_cfg}
	(printf "Section \"Device\"\n"; \
	 printf "\tIdentifier \"Card0\"\n"; \
	 printf "\tDriver \"${driver}\"\n"; \
	 printf "\tBusID \"PCI:$busID\"\n"; \
	 printf "EndSection\n") > ${path_generic_cfg}
}

run_rc_command "$1"
