#!/bin/bash
#
# rcS		Call all S??* scripts in /etc/rcS.d in
#		numerical/alphabetical order.
#

export PATH=/sbin:/bin:/usr/sbin:/usr/bin
umask 022

ROOTTMPMNT=/mnt/tmpRoot
ETCTMPMNT=/mnt/etcfs/
EFUSELISTFILE=epadEfuseData

# Start watchdog
echo 1 > /dev/watchdog

# Mount system fs
mount -t proc proc -o nosuid,noexec /proc
mount -t sysfs sysfs -o nosuid,noexec /sys
# /dev is mounted by kernel - remount with hardening flags
mount -o remount,nosuid,noexec /dev

. /etc/default/rcS
. /etc/exorint.funcs

CMDFILE=$DATAMNT/updateCmd

hwcode="$(sed 's:.*hw_code=\([0-9]\+\) .*:\1:' /proc/cmdline)"

if [ -e /sys/class/graphics/fb1/blank ]; then
	#BSP-2099 On/Off Overlay for catch error
	echo 0 > /sys/class/graphics/fb1/blank
	usleep 10000
	echo 1 > /sys/class/graphics/fb1/blank
	/bin/dmesg | /bin/grep "timeout when waiting for flip irq\|wait for bg sync eof timeout" -q
	if [ $? = 0 ]; then
		if [ -e /sys/bus/i2c/devices/0-0068/nvram ]; then
			val="$(hexdump -n1 -s1 -e '1/1 "%u"' /sys/bus/i2c/devices/0-0068/nvram)"
			[ "$val" != "0" ] && val=$(( val-1 ))
			hex_val="$( printf '%x' $val )"
			echo -ne "\x$hex_val" | dd of=/sys/bus/i2c/devices/0-0068/nvram bs=1 count=1 seek=1
			reboot -f
		fi
	fi
fi

# Trap CTRL-C &c only in this shell so we can interrupt subprocesses.
trap ":" INT QUIT TSTP

mount -t tmpfs -o rw,size=1M,nosuid,noexec tmpfs /mnt
mount --make-shared /mnt
mount -t tmpfs -o mode=0777,nodev,nosuid,noexec,strictatime,size=1M tmpfs /run

# X7 and X10, base and handheld, have increased tmpfs size
case $hwcode in
155|157)
	mount -t tmpfs -o size=320M,nosuid tmpfs /var/volatile ;;
*)
	mount -t tmpfs -o size=16M,nosuid tmpfs /var/volatile ;;
esac

mkdir -m 1777 /run/lock /var/volatile/tmp /dev/shm
mkdir -m 0755 /var/volatile/log /var/lock/subsys /mnt/media /dev/pts

mount -t devpts devpts /dev/pts -ogid=5,mode=620,nosuid,noexec

/sbin/udevd -d

# Generate SEEPROM cache
mkdir -p $SEEP_CACHE_DIR
dd if=/sys/class/i2c-dev/i2c-0/device/0-0054/eeprom of=${SEEP_CACHE_DIR}/eeprom bs=256 count=1 2>/dev/null

if [ "$(exorint_swflagarea_bit 27)" = "1" ]; then
	# Disable half cores
	nCores="$(echo /sys/devices/system/cpu/cpu[0-9]* | wc -w )"
	if [ $nCores -gt 1 ]; then
		n=$nCores
		while [ $n -gt $(($nCores/2)) ]; do
			((n--))
			echo 0 > /sys/devices/system/cpu/cpu${n}/online
		done
	fi
fi

export TMPDIR=/mnt/.psplash
mkdir $TMPDIR

# Mount factory partition to get the splash image (if mount fails, perform format+mount)
mkdir $FACTORYMNT
mount -t ext4 -o ro $FACTORYPARTITION $FACTORYMNT
if [ $? -ne 0 ]; then
	mke2fs -m 1 -T ext4 -L "factory" $FACTORYPARTITION
	mount -t ext4 -o ro $FACTORYPARTITION $FACTORYMNT
fi

# Copy /etc/shadow from etc to the factory partition if not already there
if [ ! -e $FACTORYMNT'shadow' ] || [ ! -e $FACTORYMNT'group' ] || [ ! -e $FACTORYMNT'passwd' ]; then
  mount -o remount,rw $FACTORYMNT

  if [ ! -e $FACTORYMNT'shadow' ]; then
	cp -a /etc/shadow $FACTORYMNT'shadow'
	chgrp shadow $FACTORYMNT'shadow'
  	[ -e $FACTORYMNT'machine.ini' ] && touch $FACTORYMNT'shadow.restore'
  fi
  [ ! -e $FACTORYMNT'group' ] && cp -a /etc/group $FACTORYMNT'group' && chmod 644 $FACTORYMNT'group'
  [ ! -e $FACTORYMNT'passwd' ] && cp -a /etc/passwd $FACTORYMNT'passwd' && chmod 644 $FACTORYMNT'passwd'
  mount -o remount,ro $FACTORYMNT
fi

# If EFUSELISTFILE exist then remove it
if [ -f $FACTORYMNT$EFUSELISTFILE ] ; then
  mount -o remount,rw $FACTORYMNT
  rm $FACTORYMNT$EFUSELISTFILE
  mount -o remount,ro $FACTORYMNT
fi

exorint_extfsck $ETCPARTITION
mount -t ext4 $ETCPARTITION /etc
rc=$?

# Verify etc partition is properly mounted and populated
# (if not, format and copy original /etc to it)
if [ $rc -ne 0 -o ! -d '/etc/init.d' ]; then
   # The partition does not contain a valid etc folder
   umount -l /etc
   mke2fs -m 1 -T ext4 -L "etc" $ETCPARTITION
   mkdir $ETCTMPMNT
   mount -t ext4 $ETCPARTITION $ETCTMPMNT
   cp -a /etc/. $ETCTMPMNT
   sync
   umount $ETCTMPMNT
   rm -rf $ETCTMPMNT
   mount -t ext4 $ETCPARTITION /etc
fi

# Read screen rotation settings
rotation=0
if ( "$(exorint_fparam 'screen\auto_orientation')" = "true" ); then
   autorotation=1
   rotation=$(exorint_orientation)
   [ -L /etc/rotation ] && rm /etc/rotation
   [ -L /etc/pointercal.xinput -o -e /etc/pointercal.xinput ] && rm /etc/pointercal.xinput
   echo $rotation > /etc/rotation

   # Under Xorg we also need to configure the fbdev driver
   if [ -x /usr/bin/Xorg -a ! -e "/usr/lib/xorg/modules/drivers/vivante_drv.so" ]; then
      [ -L /etc/X11/xorg.conf.d/x11-rotate.conf ] && rm /etc/X11/xorg.conf.d/x11-rotate.conf
      [ ! -d /etc/X11/xorg.conf.d ] && mkdir -p /etc/X11/xorg.conf.d

      exorint_xfbdev_rotation_config $rotation > /etc/X11/xorg.conf.d/x11-rotate.conf
   fi

elif [ -f $FACTORYMNT/etc/rotation ]; then
   read rotation < $FACTORYMNT/etc/rotation
fi

mkdir /mnt/.boot-psplash
TMPDIR=/mnt/.boot-psplash /usr/bin/psplash --angle $rotation --no-progress-bar --notouch --no-bc-reset &

if [ "$ENABLE_UDEV_CACHE" = "yes" -a -e /etc/udev.tar ]
then
    cd /
    tar xf /etc/udev.tar

    /usr/bin/udevadm control --env=STARTUP=1
    /usr/bin/udevadm trigger --action=add \
        --subsystem-match=input \
        --subsystem-match=tty \
        --subsystem-match=ttySTM

else
    # trigger the sorted events
    mknod -m 666 /dev/ptmx c 5 2
    mkdir -p /dev/pts
    mount -t devpts devpts /dev/pts -ogid=5,mode=620

    echo -e '\000\000\000\000' > /proc/sys/kernel/hotplug
    udevadm control --env=STARTUP=1
    udevadm trigger --action=add
fi

# If wayland touch calibration is missing check if we can generate it from xinput parameters
if [ -x /usr/bin/weston -a "$(exorint_cmdline_param touch_type)" = "0" -a ! -e "$FACTORYMNT/etc/udev/rules.d/touch_calibration.rules" ]; then
	exorint_cal_xinput_to_libinput
fi

# Force rotation to 270 for all X10 devices (detected by manufacturer code value).
# All these devices have a capacitive touch screen and don't require calibration parameters
case $(exorint_manufacturercode) in
594|583|590|614|615|616)
	if [ ! "$rotation" = "270" ]; then
		rotation=270
		mount -o remount,rw $FACTORYMNT
		echo $rotation > $FACTORYMNT/etc/rotation

		if [ -x /usr/bin/Xorg -a ! -e "/usr/lib/xorg/modules/drivers/vivante_drv.so" ]; then
			mkdir -p $FACTORYMNT/etc/X11/xorg.conf.d
			exorint_xfbdev_rotation_config $rotation > $FACTORYMNT/etc/X11/xorg.conf.d/x11-rotate.conf
			rm -rf /etc/pointercal.xinput $FACTORYMNT//etc/pointercal.xinput
		fi

		mount -o remount,ro $FACTORYMNT
	fi
	;;
esac

link_to_factory

# iMX vivante driver. Just let it fail for other platforms
modprobe galcore

[ -x /etc/init.d/keycode_remap ] && /etc/init.d/keycode_remap start

if [ -x /usr/bin/Xorg ]; then
	. /etc/default/xserver-nodm

	if [ -e "/usr/lib/xorg/modules/drivers/vivante_drv.so" ]; then
		# Remove fbdev rotation file under accelerated Xorg
		if [ -e "$FACTORYMNT/etc/X11/xorg.conf.d/x11-rotate.conf" ]; then
			mount -o remount,rw $FACTORYMNT
			rm "$FACTORYMNT/etc/X11/xorg.conf.d/x11-rotate.conf"
			mount -o remount,ro $FACTORYMNT
		fi
	elif [ "$rotation" != "0" -a ! -e "$FACTORYMNT/etc/X11/xorg.conf.d/x11-rotate.conf" ]; then
		# Generate fbdev rotation file if missing
		mount -o remount,rw $FACTORYMNT
		exorint_xfbdev_rotation_config $rotation > "$FACTORYMNT/etc/X11/xorg.conf.d/x11-rotate.conf"
		mount -o remount,ro $FACTORYMNT
	fi

	export DISPLAY
	if [ -n "$DPI" ] ; then
		ARGS="$ARGS -dpi $DPI"
	fi

	$XSERVER $DISPLAY $ARGS &
else
	. /etc/default/weston
	export XDG_RUNTIME_DIR

	weston-start -- $OPTARGS
fi

/etc/wm-load &

# Disable console on framebuffer to avoid showing console output
# for example when rebooting the device
echo 0 > /sys/class/vtconsole/vtcon1/bind

if [ "$SECURE_BOOT" = "yes" ]; then

	if ( which caam-keygen &>/dev/null ); then

		DECRYPTIONBLOBPATH=/mnt/factory/dm-crypt/randomkey.bb
		CAAMKEY=/tmp/caam/importKey

		if [ -e "$DECRYPTIONBLOBPATH" ]; then
			caam-keygen import $DECRYPTIONBLOBPATH importKey
		fi

		if [ ! -e "$DECRYPTIONBLOBPATH" -o ! -e "$CAAMKEY" ]; then
			caam-keygen create randomkey ecb -s 16
			mount -o remount,rw $FACTORYMNT
			mkdir -p $(dirname $DECRYPTIONBLOBPATH)
			cp /tmp/caam/randomkey.bb $DECRYPTIONBLOBPATH
			mount -o remount,ro $FACTORYMNT
			CAAMKEY=/tmp/caam/randomkey
		fi

keyctl session - << EOF
		cat $CAAMKEY | keyctl padd logon logkey: @s
		dmsetup -v create data --table "0 $(blockdev --getsz /dev/mmcblk1p8) crypt capi:tk(cbc(aes))-plain :36:logon:logkey: 0 /dev/mmcblk1p8 0 1 sector_size:512"
EOF
		rm -r /tmp/caam
	else
		DECRYPTIONBLOBPATH=/mnt/factory/dm-crypt/dm-crypt.blob

		if [ -e "$DECRYPTIONBLOBPATH" ]; then
			keyctl add caam_tk seckey "load ecb $(cat $DECRYPTIONBLOBPATH) " @u
		else
			mount -o remount,rw $FACTORYMNT
			mkdir -p "$( dirname $DECRYPTIONBLOBPATH )"
			keyctl add caam_tk seckey "new ecb 16" @u | xargs keyctl print > $DECRYPTIONBLOBPATH
			chmod 444 $DECRYPTIONBLOBPATH
			mount -o remount,ro $FACTORYMNT
		fi

		dmsetup -v create data --table "0 $(blockdev --getsz /dev/mmcblk1p8) crypt capi:tk(cbc(aes))-plain :32:caam_tk:seckey 0 /dev/mmcblk1p8 0 1 sector_size:512"
	fi

	mkdir $FITCONFIGOSMNT
	mount -t ext4 $FITCONFIGOSPARTITION $FITCONFIGOSMNT

	mkdir $FITMAINOSMNT
	mount -t ext4 $FITMAINOSPARTITION $FITMAINOSMNT
fi

exorint_extfsck $DATAPARTITION
mkdir $DATAMNT
mount -t ext4 $DATAPARTITION $DATAMNT
if [ $? -ne 0 ]; then
	mke2fs -m 1 -T ext4 -L "data" $DATAPARTITION
	mount -t ext4 $DATAPARTITION $DATAMNT
fi

if [ -e "$DATAMNT/.resizeFS" ]; then
	resize2fs $DATAPARTITION
	rm $DATAMNT/.resizeFS
	sync
fi

chgrp data $DATAMNT
chmod 2774 $DATAMNT

if [ -e $DATA2PARTITION ]; then
	exorint_extfsck $DATA2PARTITION
	mkdir -p $DATA2MNT
	mount -t ext4 $DATA2PARTITION $DATA2MNT
	if [ $? -ne 0 ]; then
		mke2fs -m 1 -T ext4 -L "data2" $DATA2PARTITION
		mount -t ext4 $DATA2PARTITION $DATA2MNT
	fi
	chgrp data $DATA2MNT
	chmod 2774 $DATA2MNT
fi

exorint_fix_settings /mnt

# Move /home to data partition
[ ! -d "$DATAMNT/home" ] && cp -rp /home $DATAMNT
mount -o bind $DATAMNT/home /home

# Get etc and bsp versions
read etcVers < /etc/migrations/version
read bspVers < /boot/version

# If versions do not match do postupdate
if [ ! "$etcVers" = "$bspVers" ]; then
   mkdir -p $ROOTTMPMNT
   mount -o bind / $ROOTTMPMNT
   echo V > /dev/watchdog
   . $ROOTTMPMNT/etc/migrations/postupdate.sh
   echo 1 > /dev/watchdog
   umount -l $ROOTTMPMNT
   rm -r $ROOTTMPMNT

   link_to_factory
fi

# Check if shadow in final etc partition is a link to a valid file
if [ ! -L /etc/'shadow' ]; then
  ln -s -b $FACTORYMNT'shadow' /etc/'shadow'
  sync
fi
[ ! -L /etc/group ] && ln -s -b -f $FACTORYMNT'group' /etc/'group' && sync
[ ! -L /etc/passwd ] && ln -s -b -f $FACTORYMNT'passwd' /etc/'passwd' && sync

exorint_hw_fixes

# Apply default settings.
# Default settings are applied if EPAD defaults are missing or if a machine.ini not yet configured is found.
# In addition, network and users defaults can be applied separately if required.
if [ ! -e /etc/EPAD/system.ini ] || [ ! -e /etc/configured -a -e $FACTORYMNT/machine.ini ]; then
   echo V > /dev/watchdog
   exorint_apply_default_settings
   reboot -f
else
   [ ! -e /etc/network/interfaces ] && def_apply="network"
   [ -e $FACTORYMNT'shadow.restore' ] && def_apply="$def_apply users"

   if [ -n "$def_apply" ]; then
      echo V > /dev/watchdog
      exorint_apply_default_settings $def_apply
      reboot -f
   fi
fi

mkdir $CONFIGOSMNT
mount -t ext4 -o ro $CONFIGOSPARTITION $CONFIGOSMNT

if [ -e $CMDFILE ]; then
   echo V > /dev/watchdog
   /etc/updateCmd.sh
fi

# Call all parts in order
exec /etc/init.d/rc S
