#!/bin/bash
# Author: Steven Shiau <steven _at_ nchc org tw>
# License: GPL
# Description: Program to make USB flash drive (FAT format) bootable by syslinux

# 1. Checking if partition table correct (on boundary, bootable)
# 2. cat mbr
# 3. syslinux -fs
#
prog="$(basename $0)"

#
[ -z "$SETCOLOR_SUCCESS" ] && SETCOLOR_SUCCESS="echo -en \\033[1;32m"
[ -z "$SETCOLOR_FAILURE" ] && SETCOLOR_FAILURE="echo -en \\033[1;31m"
[ -z "$SETCOLOR_WARNING" ] && SETCOLOR_WARNING="echo -en \\033[1;33m"
[ -z "$SETCOLOR_NORMAL"  ] && SETCOLOR_NORMAL="echo -en \\033[0;39m"
BOOTUP="color"

#
USAGE() {
   echo "Usage: $prog partition_device"
   echo "Ex:" 
   echo "To make /dev/sdc1 bootable on Linux:"
   echo "  $prog /dev/sdc1"
}

#
export LANG=C

target_part="$1"

#
if [ -z "$target_part" ]; then
  echo "No target partition was assigned!"
  USAGE
  exit 1
fi

# Make sure target_part is partition device name, not disk device name
if [ -z "$(echo $target_part | grep -iE "/dev/[hs]d[a-z]+[[:digit:]]+")" ]; then
  [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
  echo "\"$target_part\" is NOT a valid partition name!"
  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
  USAGE
  exit 1
fi

#
pt_dev="$(basename $target_part)"  # e.g. sdc1
hd_dev="${pt_dev:0:3}"   # e.g. sdc
target_disk="/dev/$hd_dev"  # e.g. /dev/sdc
pt_dev_no="${pt_dev/$hd_dev}"  # e.g. 1

# Get machine info:
on_this_machine=""
if type dmidecode &>/dev/null; then
  machine_name="$(dmidecode -s system-product-name 2>/dev/null | head -n 1)"
  if [ -z "$machine_name" -o "$machine_name" = "To Be Filled By O.E.M." ]; then
    dev_model_shown="Unknown product name"
  else
    dev_model_shown="$machine_name"
  fi
fi
on_this_machine="on this machine \"$dev_model_shown\""

#
if ! grep -qEw $pt_dev /proc/partitions; then
  [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
  echo "$target_part was NOT found!"
  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
  echo "Available disk(s) and partition(s) $on_this_machine :"
  echo "--------------------------------------------"
  cat /proc/partitions
  echo "--------------------------------------------"
  echo "Program terminated!"
  exit 1
fi

#
[ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
echo "This command will install MBR and syslinux bootloader on this machine"
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
echo "--------------------------------------------"
[ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
echo "Machine: $dev_model_shown:"
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
fdisk -l $target_disk
echo "--------------------------------------------"
echo "Are you sure you want to continue ?"
echo -n "[Y/n] "
read continue_ans
case "$continue_ans" in
  n|N|[nN][oO])
     echo "Program terminated!"
     exit 1
     ;;
esac


# 0. Check if partition is a FAT partition
# parted -s /dev/hda1 print
# Disk /dev/hda1: 8590MB
# Sector size (logical/physical): 512B/512B
# Partition Table: loop
# 
# Number  Start   End     Size    File system  Flags
#  1      0.00kB  8590MB  8590MB  fat32           
if [ -z "$(parted -s $target_disk print | grep -E "^[[:space:]]*${pt_dev_no}\>" |  grep -iE "(fat16|fat32|vfat)")" ]; then
  [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
  echo "$target_part: this doesn't look like a valid FAT filesystem"
  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
  echo "Program terminated!"
  exit 1
fi

# 1. Check if partition start/end on cylinder boundary
if [ -n "$(fdisk -l $target_disk | grep -iE "(not start on cylinder boundary|not end on cylinder boundary)")" ]; then
  [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
  echo "Some partition does not start or end on cylinder boundary! This disk will not be able to boot via syslinux!" 
  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
  echo "Program terminated!"
  exit 1
fi

# 2. Bootable ?
bootable="$(fdisk -l $target_disk | grep -Ew "^$target_part" | awk -F" " '{print $2}')"
if [ "$bootable" != "*" ]; then
  echo "$pt_dev is not marked as bootable! The partition table of $target_disk:"
  echo "--------------------------------------------"
  echo $dev_model_shown:
  fdisk -l $target_disk
  echo "--------------------------------------------"
  [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
  echo "Do you want to mark it as bootable ?"
  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
  echo -n "[Y/n] "
  read make_boot_ans
  case "$make_boot_ans" in
    n|N|[nN][oO])
       echo "Program terminated!"
       exit 1
       ;;
  esac
  echo "Running: parted -s $target_disk set $pt_dev_no boot on"
  parted -s $target_disk set $pt_dev_no boot on
fi

# 3. MBR
[ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
echo "Do you want to install mbr on $target_disk $on_this_machine ?"
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
echo -n "[Y/n] "
read make_mbr_ans
case "$make_mbr_ans" in
  n|N|[nN][oO])
     echo "Program terminated!"
     exit 1
     ;;
esac
echo "Running: cat ../mbr/mbr.bin > $target_disk"
cat ../mbr/mbr.bin > $target_disk

# 4.
[ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
echo "Do you want to install the SYSLINUX bootloader on $target_part $on_this_machine ?"
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
echo -n "[Y/n] "
read make_syslinux_ans
case "$make_syslinux_ans" in
  n|N|[nN][oO])
     echo "Program terminated!"
     exit 1
     ;;
esac
# Since most of the cases when makeboot.sh is run, all the files are in FAT (USB flash drive normally uses FAT), we have to make syslinux executable.
echo "We need a filesystem supporting Unix file mode for syslinux. Copying syslinux from FAT to /tmp/..."
syslinux_tmpd="$(mktemp -d /tmp/syslinux.XXXXXX)"
cp -fv syslinux $syslinux_tmpd
chmod u+x $syslinux_tmpd/syslinux
echo "Running: $syslinux_tmpd/syslinux -fs $target_part"
$syslinux_tmpd/syslinux -fs $target_part
[ -d "$syslinux_tmpd" -a -n "$syslinux_tmpd" ] && rm -rf $syslinux_tmpd
