#!/usr/bin/env bash
#
# Author: Dmitry Razumov <asmeron@ublinux.com>
# Copyright (c) 2021-2025 UBLinux <support@ublinux.com>
#
# Initial script for Linux UBLinux
# This script are launching before starting init from initrd script
# Current dir allways must be set to root (/)
# All system path must be relative, except initrd dirs

ENABLED=no
[[ ${ENABLED} == "yes" ]] || exit 0

PATH=.:/:/usr/bin:/usr/local/bin:/usr/local/sbin

LINKATI=/etc/ld.so.conf.d/GL/standard.conf
LINKNVIDIA96=/etc/nvidia96xx/ld.so.conf
LINKNVIDIA173=/etc/nvidia173/ld.so.conf
LINKNVIDIA304=/etc/nvidia304/ld.so.conf
LINKNVIDIA340=/etc/nvidia340/ld.so.conf
LINKNVIDIA360=/etc/nvidia360/ld.so.conf
LINKNVIDIACUR=/etc/nvidia-current/ld.so.conf
LINKFBDEV=/etc/ld.so.conf.d/GL/standard.conf
NVIDIATEST="nvidia-current nvidia340 nvidia304 nvidia"
FAILSAFENVIDIA=nouveau
CREATE_XORG_CONF=yes
GLLDCONFIG=yes
BUMBLEBEE=no
OPTIRUN=
PRIMUSRUN=
VGABUSID=
INTEGRATEDVGA=yes
SORTOPT=
XFILE=etc/X11/xorg.conf
DELETE_XORG_CONF=no

DEBUGMODE=no
. usr/lib/ublinux/functions
. usr/lib/ublinux/default
debug_mode "$0" "$@"

[ -f /memory/changes/etc/ld.so.cache ] && GLLDCONFIG=no
[ -f /memory/changes/etc/X11/xorg.conf ] && CREATE_XORG_CONF=no

# forcing modes=auto for xorg.conf
#grep -q XORG_RES etc/ublinux/config || echo XORG_RES=auto >>etc/ublinux/config

# reading last hw data VGAID CARDID XDRIVER
. $HARDCONF
# reading all values from etc/ublinux/config
echo $SYSCONF | grep -q ^/ && SYSCONF=.$SYSCONF
SOURCE=${SYSCONF}/config; [ -f "${SOURCE}" ] && . ${SOURCE} 2>/dev/null
SOURCE=${SYSCONF}/video; [ -f "${SOURCE}" ] && . ${SOURCE} 2>/dev/null

# cmdline parameter has the highest priority
CLXD=$(cmdline_value xdriver)
if [ "$CLXD" ] ;then
   if [ "$CLXD" != "$XDRIVER" -a "$XDRIVER" ];then
      unset VGAID VGAVEN DELETE_XORG_CONF VGABUSID
      [ -f $XFILE ] && mv $XFILE $XFILE.$XDRIVER.bak
      CREATE_XORG_CONF=yes && GLLDCONFIG=yes
   fi
   XDRIVER=$CLXD
fi

# auto detecting hadware
[ "$INTEGRATEDVGA" != "yes" ] && SORTOPT='-r'
# scan all vga cards
NUM=$(lspci -nmm | sed s/"Class "// | grep -c '[.]. "0300"')
# using VGABUSID if specified
[ "$VGABUSID" ] && CARD=$(lspci -nmm | sed s/"Class "// | grep ^"$VGABUSID" | head -n1)
# trying to find VGA card for specidied XDRIVER
[ -z "$CARD" -a "$XDRIVER" = "intel" ] && CARD=$(lspci -nmm | sed s/"Class "// | grep '0300" "8086"' | sort $SORTOPT | head -n1)
[ -z "$CARD" -a "$XDRIVER" = "ati" ]   && CARD=$(lspci -nmm | sed s/"Class "// | grep '0300" "1002"' | sort $SORTOPT | head -n1)
[ -z "$CARD" -a "$XDRIVER" = "nouveau" ]   && CARD=$(lspci -nmm | sed s/"Class "// | grep '0300" "10de"' | sort $SORTOPT | head -n1)
echo "$XDRIVER" | grep -q nvidia && [ -z "$CARD" ] && CARD=$(lspci -nmm | sed s/"Class "// | grep '0300" "10de"' | sort $SORTOPT | head -n1)
# if card are not found we are getting first/last card (it depends of INTEGRATEDVGA)
[ -z "$CARD" ] && CARD=$(lspci -nmm | sed s/"Class "// | grep '[.]. "0300"' | sort $SORTOPT | head -n1)

PCIID=$(echo $CARD | awk -F\" '{print $6}')
PCIVEN=$(echo $CARD | awk -F\" '{print $4}')

# in case video was changed
if [ "$PCIID" != "$VGAID" -a "$VGAID" ] ;then
   [ -f $XFILE ] && mv $XFILE $XFILE.$VGAVEN:$VGAID.bak
   unset VGAID VGAVEN DELETE_XORG_CONF VGABUSID
   CREATE_XORG_CONF=yes && GLLDCONFIG=yes
   XDRIVER=$CLXD
fi

# deleting xorg.conf when xdriver=xorg specified
[ "$XDRIVER" = "xorg" ] && DELETE_XORG_CONF=yes && CREATE_XORG_CONF=no && XDRIVER=

# setting VGABUSID only on multicard hardware
[ "$NUM" != "1" ] && VGABUSID=$(echo $CARD | awk '{print $1}')

# looking exceptions
if [ -z "$XDRIVER" ] ; then
   XDRIVER=$(grep -im1 ^$PCIVEN:$PCIID usr/share/ublinux/hwdata/xdriver/* | awk -F: '{print $1}')
   [ -z "$XDRIVER" ] || XDRIVER=$(basename $XDRIVER)
fi

# detecting XDRIVER
if [ -z "$XDRIVER" ] ; then
   [ "$PCIVEN" = "8086" ] && XDRIVER=intel
   [ "$PCIVEN" = "1002" ] && XDRIVER=ati
   [ "$PCIVEN" = "10de" ] && XDRIVER=nvidia
fi

# testing nonfree nvidia modules (nvidia-current nvidia340 nvidia304 nvidia)
if echo "$XDRIVER" | grep -q "nvidia"  ;then
   XDRIVERTESTED=
   XDRIVERCURRENT=$XDRIVER
   [ "$XDRIVER" = "nvidia" ] && XDRIVERCURRENT=
   for a in $XDRIVERCURRENT $NVIDIATEST ;do
       chroot . modprobe $a
       lsmod | grep -q nvidia && XDRIVERTESTED=$a
       [ -z "$XDRIVERTESTED" ] || break
   done
   [ -z "$XDRIVERTESTED" ] || XDRIVER=$XDRIVERTESTED
   # nouveau driver
   [ -z "$XDRIVERTESTED" ] && XDRIVER=$FAILSAFENVIDIA
fi

# storing data in config file
if [ ! -z "$XDRIVER" ] ;then
   sed -i /^XDRIVER=/d $HARDCONF
   sed -i /^VGAID=/d $HARDCONF
   sed -i /^VGAVEN=/d $HARDCONF
   sed -i /^VGABUSID=/d $HARDCONF
   sed -i /DELETE_XORG_CONF=/d $HARDCONF
   echo XDRIVER=$XDRIVER >> $HARDCONF
   echo VGAID=$PCIID >> $HARDCONF
   echo VGAVEN=$PCIVEN >> $HARDCONF
   [ "$DELETE_XORG_CONF" = "yes" ] && echo DELETE_XORG_CONF=yes >> $HARDCONF
   [ "$VGABUSID" ] && echo VGABUSID=$VGABUSID >> $HARDCONF
fi

# removing blocking conflict modules if its forced
[ "$XDRIVER" = "nouveau" ] && sed -i /^blacklist.*nouveau/d etc/modprobe.d/blacklist-ublinux.conf
echo "$XDRIVER" | grep -q "nvidia" && sed -i /^blacklist.*nvidia/d etc/modprobe.d/blacklist-ublinux.conf

# first run ldconfig tweak
if [ "$GLLDCONFIG" = "yes" ] ;then
  LINK=$LINKFBDEV
  [ "$XDRIVER" = "ati" ] && LINK=$LINKATI
  [ "$XDRIVER" = "nvidia" -o "$XDRIVER" = "nvidia-current" ] && LINK=$LINKNVIDIACUR
  [ "$XDRIVER" = "nvidia96" ] && LINK=$LINKNVIDIA96
  [ "$XDRIVER" = "nvidia173" ] && LINK=$LINKNVIDIA173
  [ "$XDRIVER" = "nvidia304" ] && LINK=$LINKNVIDIA304
  [ "$XDRIVER" = "nvidia340" ] && LINK=$LINKNVIDIA340
  [ "$XDRIVER" = "nvidia360" ] && LINK=$LINKNVIDIA360
  [ -x 'usr/sbin/alternatives' ] && chroot . /usr/sbin/alternatives --set gl_conf $LINK >/dev/null 2>&1
  LDCACHE=$XDRIVER
  [ -z "$LDCACHE" -o ! -d usr/share/ublinux/ld.so.cache/$LDCACHE ] && LDCACHE=fbdev
  [ -d "usr/share/ublinux/ld.so.cache/$LDCACHE" ] && cp -pfR usr/share/ublinux/ld.so.cache/$LDCACHE/* ./
fi

# create or delete xorg.conf
if [ "$DELETE_XORG_CONF" = "yes" ] ;then
    rm -f etc/X11/xorg.conf
else
   if [ "$CREATE_XORG_CONF" = "yes" ] ;then
      [ ! -z "$XDRIVER" -a -d usr/share/ublinux/xorg/$XDRIVER ] && cp -pfR usr/share/ublinux/xorg/$XDRIVER/* etc/X11
      [ -d usr/share/ublinux/xorg/$PCIVEN       ] && cp -pfR usr/share/ublinux/xorg/$PCIVEN/*  etc/X11
      [ -d usr/share/ublinux/xorg/$PCIVEN$PCIID ] && cp -pfR usr/share/ublinux/xorg/$PCIVEN$PCIID/* etc/X11
   fi
fi

# bumblebee service for nvidia optimus card
[ "$XDRIVER" = "intel" ] && lspci -nmm | sed s/"Class "// | grep -q '"0302" "10de"' && BUMBLEBEE=yes
[ -f etc/bumblebee/bumblebee.conf ] || BUMBLEBEE=no
if [ "$BUMBLEBEE" = "yes" ] ;then
   rm -f etc/systemd/system/bumblebeed.service
   ln -sf /lib/systemd/system/bumblebeed.service etc/systemd/system/graphical.target.wants/bumblebeed.service

   # test for kernel module
   [ -z "$BUMBLEBEEDRIVER" ] && for a in $NVIDIATEST ;do
       chroot . modprobe $a
       lsmod | grep -q nvidia && BUMBLEBEEDRIVER=$a
       [ -z "$BUMBLEBEEDRIVER" ] || break
   done
   [ -z "$BUMBLEBEEDRIVER" ] && BUMBLEBEEDRIVER=nouveau

   #settings for bumblebeed service
   sed -i /^KernelDriver=/d                                                      etc/bumblebee/bumblebee.conf
   sed -i "s/^\\[driver-nouveau\\]/\\[driver-nouveau\\]\\nKernelDriver=nouveau/" etc/bumblebee/bumblebee.conf
   if [ "$BUMBLEBEEDRIVER" = "nouveau" ] ;then
      sed -i "s/^Driver=.*/Driver=nouveau/"                                                  etc/bumblebee/bumblebee.conf
      sed -i "s/^\\[driver-nvidia\\]/\\[driver-nvidia\\]\\nKernelDriver=nvidia-current/"     etc/bumblebee/bumblebee.conf
   else
      sed -i "s/^Driver=.*/Driver=nvidia/"                                                   etc/bumblebee/bumblebee.conf
      sed -i "s/^\\[driver-nvidia\\]/\\[driver-nvidia\\]\\nKernelDriver="$BUMBLEBEEDRIVER"/" etc/bumblebee/bumblebee.conf
      [ -d "usr/lib/$BUMBLEBEEDRIVER"   ] && [ ! -h usr/lib/nvidia   ] && ln -s "$BUMBLEBEEDRIVER" usr/lib/nvidia
      [ -d "usr/lib64/$BUMBLEBEEDRIVER" ] && [ ! -h usr/lib64/nvidia ] && ln -s "$BUMBLEBEEDRIVER" usr/lib64/nvidia
   fi
   [ -z "$BBBUSID" ] && BBBUSID=$(lspci -mn | sed s/'"Class '// | awk '{ print $1 " " $2 }' | grep -m1 0302 | awk '{print $1}' | tr . :)
   [ -z "$BBBUSID" ] || sed -i s/PCI:..:..:./PCI:$BBBUSID/ etc/bumblebee/xorg.conf.nvidia
   [ -z "$BBBUSID" ] || sed -i s/PCI:..:..:./PCI:$BBBUSID/ etc/bumblebee/xorg.conf.nouveau

   echo "$OPTIRUN" | tr ',;' \\n | while read a ;do
     FILE=usr/share/applications/$a.desktop
     [ -f $FILE ] || FILE=usr/share/applications/kde4/$a.desktop
     if [ -f $FILE ] ;then
        sed -i "s|Exec=primusrun |Exec=|" $FILE
        grep -q optirun $FILE || sed -i "s|Exec=|Exec=optirun -b primus |" $FILE
     fi
   done

   echo "$PRIMUSRUN" | tr ',;' \\n | while read a ;do
     FILE=usr/share/applications/$a.desktop
     [ -f $FILE ] || FILE=usr/share/applications/kde4/$a.desktop
     if [ -f $FILE ] ;then
        sed -i "s|Exec=optirun -b primus |Exec=|" $FILE
        grep -q primusrun $FILE || sed -i "s|Exec=|Exec=primusrun |" $FILE
     fi
   done

fi

#setting BusID option for multicard hardware
if [ -f $XFILE -a "$VGABUSID" ] ;then
   VGABUSID=$(echo "$VGABUSID" | tr '.' :)
   if ! grep -q "$VGABUSID" $XFILE ;then
      a=$XDRIVER
      echo $a | grep -q nvidia && a=nvidia
      a=$(grep -i driver.*$a $XFILE)
      sed -i /BusID/d $XFILE
      sed -i /"$a"/s/$/\\n'BusID "PCI:'$VGABUSID'"'/ $XFILE
   fi
fi

#preloading kernel module to help xorg (all nvidia* modules are using one name 'nvidia')
if echo "$XDRIVER" | grep -Eq 'nvidia|nouveau' ;then
   sed -i /^nvidia/d  etc/modprobe.preload
   sed -i /^nouveau/d etc/modprobe.preload
   echo "$XDRIVER" >> etc/modprobe.preload
fi
