#!/bin/sh
#(c) Copyright Barry Kauler, 15 March 2014. Licence: GPL3 (/usr/share/doc/legal).
#simple mechanism to boot Quirky as live-CD, totally in RAM.
#150317 frugal: if file BOOT_SPECS exists, has BOOT_DEV, BOOT_FS, BOOT_FOLDER, with q.sfs separate from initrd. refer: /usr/sbin/installquirky, savesession
#150318 /var is a symlink into /tmp, ditto for /run. 151105 removed.
#151105 complete rewrite, create a layered f.s. with q.sfs underneath, zram on top.
#151106 handle low-RAM situation, maybe not run entirely in RAM. load a saved session. specs on commandline. 151109
#151111 bug fix, low-ram test.
#151122 support BOOT_DEV=UUID=<uuid>. ex kernel cmdline: boot_specs=UUID=1234-4567-6789-4321:ext2:
#151124 scan loop for usb drives (requires my usb-storage patch). 151125 nah, just sleep.

mount -t proc none /proc
mount -t sysfs none /sys
mount -t rootfs -o remount,rw rootfs /
ln -s /proc/mounts /etc/mtab 2> /dev/null
PATH="/bin:/sbin"

#allow boot specs to be on kernel commandline...
[ $boot_specs ] && BOOT_SPECS="$boot_specs"
if [ "$BOOT_SPECS" ];then
 #format: $BOOT_DEV:$BOOT_FS:$BOOT_FOLDER
 BOOT_DEV="$(echo -n "$BOOT_SPECS" | cut -f 1 -d ':')"
 BOOT_FS="$(echo -n "$BOOT_SPECS" | cut -f 2 -d ':')"
 BOOT_FOLDER="$(echo -n "$BOOT_SPECS" | cut -f 3 -d ':')"
 echo -e "BOOT_DEV=${BOOT_DEV}\nBOOT_FS=${BOOT_FS}\nBOOT_FOLDER=${BOOT_FOLDER}" > /BOOT_SPECS
fi

#create zram on /q_rw (takes about 0.8sec)...
FREEK=`grep '^MemFree:' /proc/meminfo | tr -s ' ' | cut -f 2 -d ' '`
#allocate 3/4 of free ram times 2 (as compression is approx 2:1)...
HALFK=$(($FREEK/2))
QTRK=$(($HALFK/2))
USEK=$(($HALFK+$QTRK)) #3/4
ALLOCK=$(($USEK*2))
echo "Creating compressed zram, using ${USEK}K of RAM"
echo "${ALLOCK}K" > /sys/block/zram0/disksize
echo "${USEK}K" > /sys/block/zram0/mem_limit
mkfs.ext2 -m 0 -L qrw /dev/zram0 > /dev/null 2>&1
sync
mount -t ext2 /dev/zram0 /q_rw

QPATH=''; KEEPMNT=0; xBOOT_DEV=''
if [ -f /BOOT_SPECS ];then
. /BOOT_SPECS
 mkdir /partition
 if [ "${BOOT_DEV:0:4}" == "UUID" ];then #151122. 151124 scan-loop. 151125
  #refer: http://bkhome.org/news/?viewDetailed=00297
  sleep 2
  #echo 'Scanning USB drives...'
  #sleep 1
  #while [ 1 ];do
  # sleep 0.25
  # DMESG="$(dmesg)"
  # CNTfound=$(echo "$DMESG" | grep 'usb-storage: device found at ' | wc -l)
  # CNTscanned=$(echo "$DMESG" | grep 'usb-storage: device scan complete' | wc -l)
  # [ $CNTscanned -ge $CNTfound ] && break
  #done
  xBOOT_DEV="$(blkid | grep "\"${BOOT_DEV:5}\"" | cut -f 1 -d ':' | cut -f 3 -d '/')"
 else
  xBOOT_DEV="$BOOT_DEV"
 fi
 mount -o rw -t $BOOT_FS /dev/$xBOOT_DEV /partition
 QPATH="/partition/${BOOT_FOLDER}"
fi

#setup bottom layer, with q.sfs mounted in it...
echo "Setting up layered filesystem, zram on top, Quirky SFS underneath"
QSFSbytes0=`ls -l ${QPATH}/q.sfs | tr -s ' ' | cut -f 5 -d ' '`
QSFSbytes1=$(($QSFSbytes0+500000))
mount -t tmpfs -o size=${QSFSbytes1} tmpfs /q_ro
mkdir /q_ro/q_sfs
if [ $FREEK -lt 1000000 -a "$QPATH" != "" ];then #151106 low ram. 151111 change 1000 to 1000000
 #do not copy q.sfs into ram, mount where it is...
 mount -r -t squashfs -o noatime,loop ${QPATH}/q.sfs /q_ro/q_sfs
 KEEPMNT=1
else
 if [ "$QPATH" ];then
  cp -a ${QPATH}/q.sfs /q_ro/
 else
  mv -f /q.sfs /q_ro/ #save ram space by moving
 fi
 mount -r -t squashfs -o noatime,loop /q_ro/q.sfs /q_ro/q_sfs
fi

#151106 load a saved session...
if [ -f ${QPATH}/s.sfs ];then
 echo "Loading session from ${xBOOT_DEV}, folder ${BOOT_FOLDER}, into RAM"
 mkdir -p ${QPATH}/s_sfs
 mount -r -t squashfs -o noatime,loop ${QPATH}/s.sfs ${QPATH}/s_sfs
 cp -a ${QPATH}/s_sfs/* /q_rw/
 sync
 umount ${QPATH}/s_sfs
fi

sync
[ $KEEPMNT -eq 0 ] && [ "$QPATH" ] && umount /dev/$xBOOT_DEV

#setup the layered f.s...
mount -t aufs -o udba=reval,diropq=w,dirs=/q_rw=rw:/q_ro/q_sfs=ro layerfs /q_new

echo "Performing a switch_root onto the layered filesystem"
#move the mount points...
if [ ! -d /q_new/initrd ];then
 mkdir /q_new/initrd
 mkdir /q_new/initrd/q_ro
 mkdir /q_new/initrd/q_rw
 mkdir /q_new/initrd/partition
fi
[ $KEEPMNT -eq 1 ] && mount -o move /partition /q_new/initrd/partition
mount -o move /q_ro /q_new/initrd/q_ro
mount -o move /q_rw /q_new/initrd/q_rw

#copy all of initrd-tree, for use by script 'savesession':
if [ ! -d /q_new/boot/initrd-tree ];then
 mkdir -p /q_new/boot/initrd-tree
 cp -a /bin /q_new/boot/initrd-tree/
 cp -a /dev /q_new/boot/initrd-tree/
 cp -a /etc /q_new/boot/initrd-tree/
 cp -a /sbin /q_new/boot/initrd-tree/
 cp -a /init /q_new/boot/initrd-tree/
 mkdir /q_new/boot/initrd-tree/lib
 mkdir /q_new/boot/initrd-tree/mnt
 mkdir /q_new/boot/initrd-tree/proc
 mkdir /q_new/boot/initrd-tree/q_new
 mkdir /q_new/boot/initrd-tree/q_ro
 mkdir /q_new/boot/initrd-tree/q_rw
 mkdir /q_new/boot/initrd-tree/sys
 mkdir /q_new/boot/initrd-tree/tmp
 mkdir /q_new/boot/initrd-tree/var
fi
[ -f /BOOT_SPECS ] && cp -a -f /BOOT_SPECS /q_new/boot/initrd-tree/

#need to do this before switch_root...
mount -t devtmpfs devtmpfs /q_new/dev

sync
umount /sys
umount /proc
exec switch_root /q_new /sbin/init

###END###
