#!/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

ETCTMPMNT=/mnt/etcfs/
EFUSELISTFILE=epadEfuseData

# 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

( df / | sed -n 2p | grep -qv '^/dev' ) && LIVE_MODE=1

DATAMNTLIVE=$DATAMNT
[ -n "$LIVE_MODE" ] && DATAMNT=/mnt/data-mmc/

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
# exec on volatile mount is required for updates
mount -t tmpfs -o size=16M,nosuid tmpfs /var/volatile

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

# 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

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

mkdir $ETCTMPMNT

# creates a temporary rambased etcfs
mount -o bind /etc $ETCTMPMNT
# mount a volatile temporary fs in /etc copying files from original /etc
mount -t tmpfs -o rw,size=24M tmpfs /etc
cp -a $ETCTMPMNT/* /etc/
umount $ETCTMPMNT
rmdir $ETCTMPMNT

# Udev gets confused by etc migration in tmpfs.
# It needs to be executed after etc setup
/sbin/udevd -d

# Post-processing - setup other links to factory (global settings)
if [ -z "$LIVE_MODE" ]; then
	[ -e $FACTORYMNT/etc/udev/rules.d/touch_calibration.rules -a ! -L /etc/udev/rules.d/touch_calibration.rules ] && ln -sf $FACTORYMNT/etc/udev/rules.d/touch_calibration.rules /etc/udev/rules.d/touch_calibration.rules
	[ ! -L /etc/pointercal.xinput ] && ln -sf $FACTORYMNT/etc/pointercal.xinput /etc/pointercal.xinput
	[ ! -L /etc/rotation ] && ln -sf $FACTORYMNT/etc/rotation /etc/rotation
	[ ! -L /etc/X11/xorg.conf.d/x11-rotate.conf ] && mkdir -p /etc/X11/xorg.conf.d && \
		ln -sf $FACTORYMNT/etc/X11/xorg.conf.d/x11-rotate.conf /etc/X11/xorg.conf.d/x11-rotate.conf
else
	[ -e $FACTORYMNT/etc/udev/rules.d/touch_calibration.rules ] && cp $FACTORYMNT/etc/udev/rules.d/touch_calibration.rules /etc/udev/rules.d/touch_calibration.rules
	[ -e $FACTORYMNT/etc/pointercal.xinput ] && cp $FACTORYMNT/etc/pointercal.xinput /etc/pointercal.xinput
	[ -e $FACTORYMNT/etc/rotation ] && cp $FACTORYMNT/etc/rotation /etc/rotation
	[ -e $FACTORYMNT/etc/X11/xorg.conf.d/x11-rotate.conf ] && mkdir -p /etc/X11/xorg.conf.d && \
		cp  $FACTORYMNT/etc/X11/xorg.conf.d/x11-rotate.conf /etc/X11/xorg.conf.d/x11-rotate.conf
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

# 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

export ROTATION  # for other scripts - e.g. updateCmd

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

# Trigger input udev subsystem
udevadm trigger --action=add --subsystem-match=input
udevadm settle

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 &

	/etc/wm-load &
fi

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

# Leave all other triggers in background
udevadm trigger --action=add \
    --subsystem-match=usb \
    --subsystem-match=i2c \
    --subsystem-match=spi \
    --subsystem-match=iio \
    --subsystem-match=block \
    --subsystem-match=leds \
    --subsystem-match=tty \
    --subsystem-match=mem \
    --subsystem-match=graphics \
    --subsystem-match=drm \
    --subsystem-match=gpu_class \
    --subsystem-match=misc \
    --subsystem-match=gpio \
    --subsystem-match=rtc \
    --subsystem-match=platform \
    --subsystem-match=video4linux \
    --subsystem-match=hwmon

# 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

if [ -z "$LIVE_MODE" ]; then
	ln -s -b $FACTORYMNT'shadow' /etc/shadow
	ln -s -b -f $FACTORYMNT'group' /etc/'group'
	ln -s -b -f $FACTORYMNT'passwd' /etc/'passwd'
else
	chgrp shadow /etc/shadow
fi

# Make root home writable for applications like metacity
mount -t tmpfs -o size=1M tmpfs /home/root

mkdir $MAINOSMNT
mount -t ext4 -o ro $MAINOSPARTITION $MAINOSMNT

mkdir $ETCMNT
mount -t ext4 -o ro $ETCPARTITION $ETCMNT

# use dedicated tmpfs for large fonts and cache (instead of a symlink)
# to avoid issues formatting mainos while using its fonts from configos
if [ -d ${MAINOSMNT}/usr/share/fonts/large/ ]; then
    # grab fonts
    LARGEFONTSMNT=/usr/share/fonts/large/
    mount -t tmpfs -o rw,tmpfs,nosuid,noexec ${LARGEFONTSMNT}
    rsync -a ${MAINOSMNT}/usr/share/fonts/large/ ${LARGEFONTSMNT}
    mount -o remount,ro ${LARGEFONTSMNT}
    # grab font cache
    FONTCACHEMNT=/var/cache/fontconfig/
    mount -t tmpfs -o rw,nosuid,noexec tmpfs ${FONTCACHEMNT}
    rsync -a ${MAINOSMNT}/var/cache/fontconfig/ ${FONTCACHEMNT}
    mount -o remount,ro ${FONTCACHEMNT}
fi

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

if [ -n "$LIVE_MODE" ]; then
	mkdir $DATAMNTLIVE
	mount -t tmpfs none $DATAMNTLIVE
fi

[ -e $CMDFILE ] && /etc/updateCmd.sh

exorint_hw_fixes $hwcode

# Apply settings from machine.ini if requested
if grep -q ^applyToConfigos=true $FACTORYMNT/machine.ini; then
    exorint_apply_default_settings
fi

# Blind device management - bootcounter reset (done by psplash for HMIs)
if [ "${DEVICETYPE}" = "ROUTER" ]; then
    psplash-write "QUIT"
fi
if [ "${DEVICETYPE}" = "DEVICE" ]; then
    psplash-write "QUIT"
fi

fault_led=$( find  /sys/class/leds/*fault* )
if [ -d $fault_led ]
then
    # Blink fault led to know if we are in configos
    echo timer > $fault_led/trigger
    echo 100 >   $fault_led/delay_on
    echo 1000 >  $fault_led/delay_off
fi;

pwr_led=$( find  /sys/class/leds/pwr )
if [ -d $fault_led ]
then
    # Blink fault led to know if we are in configos
    echo timer > $pwr_led/trigger
    echo 200 >   $pwr_led/delay_on
    echo 200 >  $pwr_led/delay_off
fi;

# Set up resources to run containerized applications
mkdir /dev/mqueue
mount -t mqueue none /dev/mqueue

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