#!/bin/sh
# (c) Robert Shingledecker 2005-2013
# Portions (c) Brian Smith, 2011

. /etc/init.d/tc-functions
useBusybox

abort(){
  if [ "$DISPLAY" ] && [ "$INTERACTIVE" ]; then
    echo -n "Press Enter key."
    read gagme
  fi
  exit 1
}

checkroot

toggle_active(){     
echo "Toggle Active Flag on $DEVICE$PARTITION"
fdisk /dev/$DEVICE << EOF >/dev/null 2>&1
a
$PARTITION
w
EOF
}

partition_setup_common(){
  echo "Writing zero's to beginning of /dev/$DEVICE"
  dd if=/dev/zero of=/dev/$DEVICE bs=1k count=1 >/dev/null 2>&1 &
  sync
  
  echo "Partitioning /dev/$DEVICE"
  if [ "$FORMAT" == "vfat" ]; then
     fdisk /dev/$DEVICE << EOF >/dev/null 2>&1
n
p
1


a
1
t
c
w
EOF
  else
     fdisk /dev/$DEVICE << EOF >/dev/null 2>&1
n
p
1


a
1
t
83
w
EOF
  fi
}  
  
iso_prep(){
  # We need to mount the ISO file using the loopback driver.
  # Start by creating a mount point directory; we'll call it "staging"
  if [ -d /mnt/staging ]; then
    if mounted /mnt/staging; then umount /mnt/staging; fi
  else
    mkdir /mnt/staging
  fi  
  mount -t iso9660 -o loop,ro $SOURCE /mnt/staging
  if [ $? != 0 ]; then
    umount /mnt/drive  # unmount the target drive
    echo "Sorry $SOURCE not found!"
    echo "Installation not successful!"
    abort
  fi
  IMAGE="/mnt/staging"
  BOOT="/mnt/staging/boot/"
}
  
hdd_setup(){
  partition_setup_common 
  sync; sleep 5
  hdparm -z /dev/$DEVICE
  sync; sleep 5
  rebuildfstab
  
  echo "Formatting /dev/$TARGET"
  if [ "$FORMAT" == "vfat" ]; then
    mkdosfs /dev/$TARGET
  else
    mkfs."$FORMAT" -F -m 0 /dev/$TARGET >/dev/null
  fi
  sync; sleep 5
   
  dd if=/usr/local/share/syslinux/mbr.bin of=/dev/$DEVICE
  sync; sleep 5
}
zip_setup(){
   echo "Changing geometry for USB-ZIP compatibility on /dev/$DEVICE"
   /usr/local/bin/mkdiskimage -1 /dev/$DEVICE 16 64 32
   if [ $? != 0 ]; then
      echo "Error creating USB-ZIP compatible filesystem."
      abort
   fi
# Use remaining drive for backup/restore and tce
#
   DATA="$DEVICE"2
   echo "Partitioning /dev/$DEVICE"
   fdisk /dev/$DEVICE << EOF >/dev/null 2>&1
n
p
2


t
2
83
w
EOF
   sync; sleep 5
   hdparm -z /dev/$DEVICE
   sync; sleep 5
   echo "Formatting /dev/$DATA"
   mke2fs /dev/$DATA
   sync; sleep 5
   rebuildfstab
#
   echo "Formatting /dev/$TARGET"
   mkdosfs /dev/$TARGET
   if [ $? != 0 ]; then
      echo "Error while formatting DOS filesystem."
      abort
   fi
   sync; sleep 5
   echo "Setting up boot loader on /mnt/$TARGET"
   syslinux --install  /dev/$TARGET
   if [ $? != 0 ]; then
      echo "Error writing boot sector"
      abort
   fi
   sync; sleep 5
}

frugal_setup(){
if [ "$DEVICE" == "$TARGET" -a "$FORMAT" != "none" ]
then
  partition_setup_common
  sync; sleep 5
  hdparm -z /dev/$DEVICE
  sync; sleep 5
  rebuildfstab
fi

[ "$DEVICE" == "$TARGET" ] && TARGET="$DEVICE"1

if [ "$FORMAT" != "none" ]
then  
  echo "Formatting /dev/$TARGET"
  if [ "$FORMAT" == "vfat" ]; then
    mkfs.vfat /dev/$TARGET
  else
    mkfs."$FORMAT" -F -m 0 /dev/$TARGET >/dev/null
  fi
  sync;sleep 5
fi

[ "$BOOTLOADER" == "yes" ] && dd if=/usr/local/share/syslinux/mbr.bin of=/dev/$DEVICE
[ "$BOOTLOADER" == "yes" ] && sync; sleep 5

if [ "$MARKACTIVE" == "1" ]; then
  ACTIVE=$(fdisk -l 2>/dev/null | grep "^/dev/$DEVICE" | grep '*' | cut -f1 -d' ')
  if [ -n "$ACTIVE" ]; then                                                       
    for i in "$ACTIVE"; do                                                       
      echo "$i"
      PARTITION="${i:8}"                                                       
      toggle_active     
    done                 
  fi                     
  PARTITION="${TARGET:3}"
  toggle_active 
  hdparm -z /dev/$DEVICE
  sync; sleep 5
fi
}

syslinux_setup(){
  [ "$BOOTLOADER" == "yes" ] && echo "Applying syslinux."
  [ "$BOOTLOADER" == "yes" ] && /usr/bin/syslinux --install /dev/$TARGET
  sync; sleep 5

  echo "Setting up $ROOTFS image on /mnt/$TARGET"
  mount /dev/$TARGET /mnt/drive
  if [ $? != 0 ]; then
     echo "Error mounting device"
     abort
  fi
  [ "$BOOTLOADER" == "yes" ] && [ -d $BOOTDIR ] || mkdir -p $BOOTDIR
  [ -d /mnt/drive/tce ] || mkdir -p /mnt/drive/tce/sce
  
  cp  $BOOT/vmlinuz $BOOTDIR
  cp  $BOOT/"$ROOTFS".gz $BOOTDIR
  
  if [ "$BOOTLOADER" == "yes" ]; then
  	echo "DEFAULT $ROOTFS" > /mnt/drive/syslinux.cfg
  	echo "LABEL $ROOTFS" >> /mnt/drive/syslinux.cfg
  	echo "KERNEL $BOOTPATH/vmlinuz" >> /mnt/drive/syslinux.cfg
  	echo "APPEND initrd=$BOOTPATH/$ROOTFS.gz quiet waitusb=5:"$TARGETUUID" tce="$TARGETUUID" " >> /mnt/drive/syslinux.cfg
  	sync
  	sed -i s"~quiet~quiet $OPTIONS~" /mnt/drive/syslinux.cfg
  fi
  
  sync
  [ -f /mnt/drive/tce/${MYDATA}.tgz ] || touch /mnt/drive/tce/${MYDATA}.tgz
  umount /mnt/drive
  echo "Installation has completed"
}

zip_update(){
  DATA="$DEVICE"2
  DATAUUID=`/sbin/blkid -s UUID /dev/"$DATA"|cut -f2 -d\ `
  echo "Setting up boot image on /mnt/$TARGET"
  mount -t vfat /dev/$TARGET /mnt/drive
  if [ $? != 0 ]; then
    echo "Error mounting usb device partition 1"
    abort
  fi
  echo "Setting up $ROOTFS image on /mnt/$TARGET"
  cp  $BOOT/vmlinuz /mnt/drive/
  cp  $BOOT/"$ROOTFS".gz /mnt/drive
  sync; sleep 5
  echo "DEFAULT $ROOTFS" > /mnt/drive/syslinux.cfg
  echo "LABEL $ROOTFS" >> /mnt/drive/syslinux.cfg
  echo "KERNEL vmlinuz" >> /mnt/drive/syslinux.cfg
  echo "APPEND initrd=$ROOTFS.gz quiet waitusb=5:"$DATAUUID" tce="$DATAUUID" " >> /mnt/drive/syslinux.cfg
  sync; sleep 5
  sed -i s"~quiet~quiet $OPTIONS~" /mnt/drive/syslinux.cfg
  sync; sleep 5
  umount /mnt/drive
  mount /dev/$DATA /mnt/drive
  if [ $? != 0 ]; then
    echo "Error mounting usb device partition 2"
    abort
  fi
  [ -d /mnt/drive/tce ] || mkdir -p /mnt/drive/tce/sce
  touch /mnt/drive/tce/${MYDATA}.tgz
  umount /mnt/drive
  echo "Installation has completed"
}

extlinux_setup(){
  sync; sleep 5
  mount /dev/$TARGET /mnt/drive
  if [ $? != 0 ]; then
    echo "Error mounting usb device"
    abort
  fi

  [ "$BOOTLOADER" == "yes" ] && echo "Applying extlinux."
  [ "$BOOTLOADER" == "yes" ] && [ -d $BOOTDIR/extlinux ] || mkdir -p $BOOTDIR/extlinux
  [ "$BOOTLOADER" == "yes" ] && /usr/local/sbin/extlinux -i $BOOTDIR/extlinux
  sync; sleep 5

  echo "Setting up $ROOTFS image on /mnt/$TARGET"
  [ -d /mnt/drive/tce ] || mkdir -p /mnt/drive/tce/sce
  
  cp  $BOOT/vmlinuz $BOOTDIR
  cp  $BOOT/"$ROOTFS".gz $BOOTDIR
  
  if [ "$BOOTLOADER" == "yes" ]; then
  
	# check for a Windows partition and if found make a boot menu.
	  WINDOWS="$(fdisk -l 2>/dev/null | grep "^/dev/${TARGET:0:3}" | awk '
	  {  
	    type = substr($0,52,2)
	    if (type == " 7" || type == " b" || type == " c") {
	      results = substr($1,9)
	      print results
	    }
	  } ' )"
  
	  > $BOOTDIR/extlinux/extlinux.conf
  
	  if [ -n "$WINDOWS" ]; then
	    if [ "$TYPE" == "frugal" ] && [ "$MARKACTIVE" == "1" ]; then
	      echo "Setting up menu for Windows and Tiny Core"
	      cp /usr/lib/syslinux/vesamenu.c32 $BOOTDIR/extlinux/.
	      cp /usr/lib/syslinux/chain.c32 $BOOTDIR/extlinux/.
	      echo "UI vesamenu.c32" >> $BOOTDIR/extlinux/extlinux.conf
	      echo "MENU TITLE Tiny Core Bootloader" >> $BOOTDIR/extlinux/extlinux.conf
	      echo "TIMEOUT 100" >> $BOOTDIR/extlinux/extlinux.conf
	      echo "" >> $BOOTDIR/extlinux/extlinux.conf
	    fi
	  fi
  
	  echo "DEFAULT $ROOTFS" >> $BOOTDIR/extlinux/extlinux.conf
	  echo "LABEL $ROOTFS" >> $BOOTDIR/extlinux/extlinux.conf
	  echo "KERNEL $BOOTPATH/vmlinuz" >> $BOOTDIR/extlinux/extlinux.conf
	  echo "APPEND initrd=$BOOTPATH/$ROOTFS.gz quiet waitusb=5:"$TARGETUUID" tce="$TARGETUUID" " >> $BOOTDIR/extlinux/extlinux.conf
  
	  if [ -n "$WINDOWS" ]; then
	    if [ "$TYPE" == "frugal" ] && [ "$MARKACTIVE" == "1" ]; then
	      echo "" >> $BOOTDIR/extlinux/extlinux.conf
	      echo "LABEL windows" >> $BOOTDIR/extlinux/extlinux.conf
	      echo "KERNEL chain.c32" >> $BOOTDIR/extlinux/extlinux.conf
	      echo "APPEND hd0 ${WINDOWS}" >> $BOOTDIR/extlinux/extlinux.conf
	    fi
	  fi
  
	  sync
	  sed -i s"~quiet~quiet $OPTIONS~" $BOOTDIR/extlinux/extlinux.conf
  fi  
  
  touch /mnt/drive/tce/${MYDATA}.tgz
  sync
  umount /mnt/drive
  echo "Installation has completed"
}

getINSTALL(){
  busybox clear
  echo
  echo "${WHITE}Core Installation.${NORMAL}"
  echo
  INSTALL="i"
  INTERACTIVE="y"
}

getROOTFS(){
  echo -n "${CYAN}Install from [R]unning OS, from booted [C]drom, or from [I]so file. ${YELLOW}(r/c/i): ${NORMAL}"
  read FROM
  case "$FROM" in
    "C" | "c")
      CDROMS=`cat /etc/sysconfig/cdroms 2>/dev/null` 
      CD="${CDROMS##*/}"
      CD="$(trim $CD)"
      [ -d /mnt/"$CD" ] && mount /mnt/"$CD" 2>/dev/null
      if [ -d /mnt/"$CD"/boot ]; then
        BOOT=/mnt/"$CD"/boot 
        [ -f "$BOOT"/vmlinuz ] || MISSING="$MISSING vmlinuz "
        OS="dCore"
        if [ -f "$BOOT"/"$OS".gz ]; then
          ROOTFS="$OS"
        else
          MISSING="$MISSING $OS.gz"
        fi
      else
         MISSING="boot directory."
      fi
      if [ -n "$MISSING" ]; then
        echo "Could not find system file(s): $MISSING"
        abort
      fi
      echo "Using: ${GREEN}$BOOT/$ROOTFS.gz${NORMAL}"
    ;; 
    "R" | "r")
      echo "Enter ${WHITE}boot directory path${NORMAL} to vmlinuz and dCore.gz."
      echo -n "${WHITE}(EXAMPLE: ${YELLOW}/mnt/sr0/boot/): ${NORMAL}"
      read BOOT
      if [ -z "$BOOT" ]; then
        echo "No path entered. The script will be terminated."
        abort
      fi 
      [ -f "$BOOT"/vmlinuz ] || MISSING="$MISSING vmlinuz "
      OS="dCore"
      if [ -f "$BOOT"/"$OS".gz ]; then
        ROOTFS="$OS"
      else
        MISSING="$MISSING $OS.gz"
      fi
      if [ -n "$MISSING" ]; then
        echo "Could not find system file(s): $MISSING"
        abort
      fi
      echo "Using: ${GREEN}$BOOT/$ROOTFS.gz${NORMAL}"
    ;;
    "I" | "i")
      # read path from user
      echo -n "${CYAN}Enter the full path to the iso.  ${WHITE}(EXAMPLE: ${YELLOW}/tmp/Core-4.7.iso): ${NORMAL}"
      read SOURCE
      if [ -z "$SOURCE" ] ; then
        echo "No path entered. The script will be terminated."
        abort
      fi
      if [ ! -f "$SOURCE" ]; then
        echo "Cound not find: $SOURCE"
        abort
      fi
      ROOTFS=dCore
    ;;
    *)
      echo "Invalid option."
      abort
    ;;
  esac

  [ -z "$BOOT" ] && iso_prep
}

getTYPE(){
  busybox clear
  echo
  echo "Select install type for ${GREEN}$BOOT/$ROOTFS.gz${NORMAL}"
  echo
  echo "${RED}Frugal${NORMAL}"
  echo "* Use for frugal ${RED}hard drive${NORMAL} installations."
  echo "${YELLOW}Note: ${NORMAL}You will be prompted for disk/partion and formatting options."
  echo
  echo "${WHITE}HDD${NORMAL}"
  echo "* Use for ${WHITE}pendrives${NORMAL}. Your BIOS must support ${WHITE}USB-HDD${NORMAL} booting."
  echo "* A single FAT partition will be made."
  echo "${YELLOW}Note: ${NORMAL}Requires dosfstools extension."
  echo "${MAGENTA}Warning: ${NORMAL}This is a whole drive installation!"
  echo
  echo "${BLUE}Zip${NORMAL}"
  echo "* Use for ${BLUE}pendrives${NORMAL}. Drive will be formatted into two FAT partitions."
  echo "* One small one for ${BLUE}USB_ZIP${NORMAL} boot compatibility, and used to hold Tiny Core."
  echo "* The remaining partition will be used for backup & extensions."
  echo "${YELLOW}Note: ${NORMAL}Requires dosfstools and perl extensions."
  echo "${MAGENTA}Warning: ${NORMAL}This is a whole drive installation!"
  echo
  echo -n "${CYAN}Select Install type [F]rugal, [H]DD, [Z]ip. ${YELLOW}(f/h/z): ${NORMAL}"
  read TYPE
  case "$TYPE" in
    "H" | "h")
      TYPE="hdd"
    ;;
    "Z" | "z")
      TYPE="zip"
    ;;
    "F" | "f")
      TYPE="frugal"
    ;;
    *)
      echo "Invalid Boot type."
      abort
    ;;
  esac

}

getBOOTLOADER(){
  busybox clear
  echo "Would you like to install a bootloader?"
  echo "Most people should answer yes unless they are trying to embed Core in to"
  echo "a different Linux distribution with an existing bootloader."
  echo
  echo -n "Enter selection ( y, n ) or (q)uit:  "
  read BOOTLOADER
  case "$BOOTLOADER" in
    "Y" | "y")
      BOOTLOADER="yes"
    ;;
    "N" | "n")
      BOOTLOADER="no"
    ;;
    "Q" | "q")
      exit
    ;;
    *)
      echo "Invalid option. "
      abort
    ;;
  esac
}

getTARGET(){
  DISKFLAG="-d"; TITLE="disk"
  if [ "$TYPE" == "frugal" ]; then
    > /tmp/tmpfile
    for i in "Whole Disk" "Partition"; do
      printf "%s\n" "$i" >> /tmp/tmpfile
    done
    select "Select Target for Installation of $ROOTFS" /tmp/tmpfile 0
    rm /tmp/tmpfile
    [ "$(cat ${SELANS})" == "q" ] && abort
    if [ "$(cat ${SELANS})" == 2 ]; then
       DISKFLAG="-p"
       TITLE="partition"
    else
       WHOLEDISK="yes" 
    fi
  else
    WHOLEDISK="yes" 
  fi
  
  fetch_devices "$DISKFLAG" > /tmp/tmpfile                                            
  select "Select $TITLE for $ROOTFS" /tmp/tmpfile 1                               
  TARGET=`awk '{print $1}' < "$SELANS"`
  rm /tmp/tmpfile                                                                 
  [ "$(cat ${SELANS})" == "q" ] && abort
  echo "$TARGET"                                                                  
  DEVICE="${TARGET:0:3}" 
  [ "$TYPE" == "frugal" ] || TARGET="$DEVICE"1
  if [ -z "$DEVICE" ] ; then
    echo "No device chosen. The script will be terminated."
    abort
  fi

  grep -q ^/dev/"$DEVICE" /etc/mtab
  if [ "$?" == 0  ]; then
    echo "$DEVICE appears to have a partition already mounted!"
    echo "Check if correct device, if so,  umount it."
    abort
  fi
}

getFORMAT(){
  if [ "$WHOLEDISK" == "yes" ]; then
    for i in "ext2" "ext3" "ext4"
    do
      printf "%s\n" "$i" >> /tmp/tmpfile
    done
  else
    for i in "none" "ext2" "ext3" "ext4"
    do
      printf "%s\n" "$i" >> /tmp/tmpfile
    done
  fi  
  
  select "Select Formatting Option for $TARGET" /tmp/tmpfile 1
  rm /tmp/tmpfile
  [ "$(cat ${SELANS})" == "q" ] && abort
  FORMAT="$(cat ${SELANS})"
}

getOPTIONS(){
  echo "${CYAN}Enter space separated boot options: "
  echo "${WHITE}Example: ${YELLOW}vga=normal syslog showapps waitusb=5${NORMAL} "
  read OPTIONS
}

#Main
KERNELVER=$(uname -r)
SELANS=/tmp/select.ans
i=0
until [ -z "$1" ]; do
  i=`busybox expr $i + 1`
  case $i in
    1) SOURCE="$1"
       if [ "${SOURCE##*.}" == "iso" ]; then
         ROOTFS=dCore
         iso_prep
         BOOT=/mnt/staging/boot
       else
         BOOT="${SOURCE%/*}"
         ROOTFS=dCore
       fi
       ;;
    2) TYPE="$1"
       ;;
    3) TARGET="$1"
       DEVICE="${1:0:3}"
       [ "$TYPE" == "frugal" ] || TARGET="$DEVICE"1
       ;;
    4) MARKACTIVE="$1"
       ;;
    5) FORMAT="$1"
       INSTALL="i"
       ;;
    6) BOOTLOADER="$1"
       ;;
    7) STANDALONEEXTENSIONS="$1"
       ;;
    *) OPTIONS="$OPTIONS $1"
       ;;
  esac
  shift
done

echo $BOOT > /tmp/install.opt
echo $ROOTFS >> /tmp/install.opt
echo $TYPE >> /tmp/install.opt
echo $DEVICE >> /tmp/install.opt
echo $TARGET >> /tmp/install.opt
echo $MARKACTIVE >> /tmp/install.opt
echo $FORMAT >> /tmp/install.opt
echo $OPTIONS >> /tmp/install.opt

[ -n "$INSTALL" ] || getINSTALL
[ -n "$ROOTFS" ] || getROOTFS
[ -n "$TYPE" ] || getTYPE
[ -n "$TARGET" ] || getTARGET
if [ "$TYPE" == "frugal" ]; then
	[ -n "$BOOTLOADER" ] || getBOOTLOADER
else
	BOOTLOADER="yes"
fi

[ -n "$STANDALONEEXTENSIONS" ] || STANDALONEEXTENSIONS="none"

if [ "$TYPE" != "zip" ]; then
  [ -n "$FORMAT" ] || getFORMAT
fi

if [ "$INTERACTIVE" ]; then
  PARTITION="${TARGET:3}"
  if [ "$TYPE" == "frugal" ] && [ -n "$PARTITION" ]; then
     ANS=""
     until [ "$ANS" == "y" ] || [ "$ANS" == "n" ]; do
        echo -n "Mark $TARGET active bootable? y/n:"; read ANS
     done
     [ "$ANS" == "y" ] && MARKACTIVE=1   
  fi
  getOPTIONS
  echo
  echo "${RED}Last chance to exit before destroying all data on ${MAGENTA}$TARGET${NORMAL}"
  echo -n "${CYAN}Continue (y/..)?${NORMAL} "
  read answer
  if [ "$answer" != "y" ]; then
    echo "Aborted.."
    abort
  fi
  echo
fi  # End of installation

grep -q ^/dev/"$DEVICE" /etc/mtab
if [ "$?" == 0  ]; then
    echo "$DEVICE appears to have a partition already mounted!"
    echo "Check if correct device, if so,  umount it and then"
    echo "run installer again."
    abort
fi

BOOTDIR="/mnt/drive/boot"
[ "$TYPE" == "frugal" ] && BOOTDIR="/mnt/drive/tce/boot"
BOOTPATH="/boot"
[ "$TYPE" == "frugal" ] && BOOTPATH="/tce/boot"

case "$TYPE" in
  "hdd") hdd_setup ;;
  "zip") zip_setup ;;
  "frugal") frugal_setup ;;
esac

rebuildfstab
[ -d /mnt/drive ] || mkdir /mnt/drive
TARGETUUID="$(blkid -s UUID /dev/${TARGET}|awk '{print $2}')"
echo "$TARGETUUID"
if [ "$TYPE" == "zip" ]; then
  zip_update
else
  if [ "$FORMAT" == "vfat" ] || ( [ "$FORMAT" == "none" ] && fdisk -l | grep "$TARGET " | grep -i fat >/dev/null ); then 
    syslinux_setup
  else 
    extlinux_setup
  fi
fi

if mounted /mnt/staging; then umount /mnt/staging; fi
if [ "$INTERACTIVE" ]; then
  echo -n "Press Enter key to continue."
  read gagme
fi
