#!/bin/bash
#
#  Copyright (C) 2004 Dell Computer Corporation <john_hull@dell.com>
#  Copyright (C) 2018 Dell Inc. <mario.limonciello@dell.com>
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# Purpose: This program can be used to quickly create a bootable DOS disk
# with a BIOS flash executable file
#
set -e

baseDir="/usr/share/biosdisk"
grubDir="/etc/grub.d"
confFile="/etc/biosdisk.conf"
libDir="/var/lib/biosdisk"
tmpPath="/tmp"
curDir=`pwd`
wget="/usr/bin/wget"
options=""

# Flags
mkImgFlag=0
installFlag=0
imgCompleteFlag=0
forceFlag=1
destSpecifiedFlag=0
file=""

if [ -e "$confFile" ]; then
    source "$confFile"
fi

destination=""

####################### Functions ########################
function showUsage()
{
    echo $"Usage: $0 [action] [options] /path/fileName.exe"
    echo $"  [action]  =  { mkimage | install | uninstall} "
    echo $"  [options] =  [-o exe_option ]"
    echo $"               [-i destination]"
    echo $"               [-h|--help]"
}

function makeImage()
{
    # Protect against involuntary overwriting
    if [ -e $destination ] && [ $forceFlag == "0" ]; then
        echo "Warning: $destination already exists! [O]verwrite/[A]bort?"
        read choice
        loop=1
        while [ $loop == 1 ]; do
            case $choice in
               O|o)
                   rm -f $destination
                   loop=0
                   ;;
               A|a)
                   echo "$0 aborted by user"
                   loop=0
                   exit 1
                   ;;
               *)
                   echo "Warning: $destination already exists! [O]verwrite/[A]bort?"
                   read choice
                   ;;
            esac
        done
    fi

    tmpMount=$(mktemp -d /tmp/biosdisk.XXXXXX)
    cp -R $baseDir/freedos-iso/* $tmpMount
    cp -f $biosFile $tmpMount/${shortBiosName}
    echo "$shortBiosName $options" >> $tmpMount/setup.bat
    mkisofs -o $destination -l -N -boot-info-table \
            -iso-level 4 -no-emul-boot -b isolinux/isolinux.bin \
            -publisher "Dell" -A "Freedos distribution" -V FDOS -v $tmpMount
}

function setupPxe()
{
    echo "Not yet supported"
    exit 1

}

function test_root()
{
    if [ `id -u` != 0 ]; then
        echo "Error: You must run $0 as root"
        exit 0
    fi
}

function install()
{
    local kernel="/boot/memdisk"
    if [ ! -f $kernel ]; then
        memdisk_done=0
        for i in /usr/lib/syslinux/memdisk /usr/lib/syslinux/bios/memdisk /usr/share/syslinux/memdisk
        do
            if [ -e $i ]; then
                cp -f $i $kernel
                memdisk_done=1
            fi
        done
        if [ $memdisk_done -eq 0 ]; then
            echo "Can't find $kernel image"
            exit 1
        fi
    fi

    if [ `dirname $destination` != "/boot" ]; then
        cp -f $destination /boot
        destination=/boot/`basename $destination`
    fi
    if [ ! -x $grubDir/42_biosdisk ]; then
        cp $baseDir/42_biosdisk $grubDir
        chmod +x $grubDir/42_biosdisk
    fi
    sed -i "s,initrd16.*,initrd16 $destination," $grubDir/42_biosdisk
    grub-mkconfig -o /boot/grub/grub.cfg
    grub-reboot "Flash BIOS"
    echo "Copied image to $destination and updated bootloader"

}

function uninstall()
{
    rm -f $grubDir/42_biosdisk
    grub-mkconfig -o /boot/grub/grub.cfg
    if [ `dirname $destination` != "/boot" ]; then
        destination=/boot/`basename $destination`
        rm -f $destination
    fi

}

# shorten names from N.3 to 8.3
function shortname()
{
    local name=$1
    local extension=${name:(-4)}
    local leftname=$(basename ${name} ${extension})
    if [ ${#leftname} -gt 8 ]; then
	echo "${leftname:0:8}${extension}"
    else
	echo "${name}"
    fi
}

###################### Main #################################

if [ $# -eq 0 ]; then
    showUsage
    exit 1
fi

if [ -d /sys/firmware/efi ]; then
    echo "Warning: biosdisk images will not work in EFI mode"
fi

eval last=\${$#}
eval sLast=\$`expr $# - 1`
# Catches incomplete switches
case $sLast in
    -[a-z])
        echo "Error: You do not seem to have specified a BiosExe"
        showUsage
        exit 1
        ;;

esac


# find biosdisk action
case $1 in
    mkimage|mkImage)
	mkImgFlag=1
        ;;
    install)
        mkImgFlag=1
        installFlag=1
        ;;
    uninstall)
        uninstallFlag=1
        ;;
    *)
        echo "Error: biosdisk action incorrect or not specified"
        showUsage
        exit 2
        ;;
esac
shift

# Work through options and act accordingly
while [ $# -gt 0 ]; do
    if [ "$1" -a "$2" ]; then
        case $1 in
            -o)
                options="$options $2"
                shift
                ;;
            -i)
                destination=$2
                destSpecifiedFlag=1
                shift
                ;;
            *)
                echo "Error: $0 does not take \"$1 $2\" as an option"
                showUsage
                exit 1
		;;
        esac
    elif [ "$1" -a -z"$2" ]; then
        case $1 in
            -h|--help)
                showUsage
                exit 1
                ;;
            *)
             # Testing for validity of last argument which should be raw bios or image file
             # If we're here but not on the last argument, the user wrote gibberish

               if [ $last == $1 ]; then
                    if [ ! -f $1 ] && ! [ `echo $1 | grep -c "^[fhFH][tT][Tt]*[pP]"` -eq 1 ]; then
                        echo "Error: \"$1\" treated as a file, but its not useable/nonexistent"
                        showUsage
                        exit 1
                    else
                        #If file is url, then get it
                        if [ `echo $1 | grep -c "^[fhFH][tT][Tt]*[pP]"` -eq 1 ]; then
                            if ! [ -x $wget ]; then
                                echo "Can't find $wget. Please install wget on your system"
                                exit 1
                            fi
                            file=$libDir/`basename $1`
			    $wget -O $file $1
                            if ! [ -f $file ]; then
                                echo "Error: could not download file!"
                                exit 1
                            fi
                        else
                            file=$1
                        fi
			# In case the download did not work (timeout, programme not found)

			if [ ! -f $file ]; then
			    echo "Error: Cannot find/use $file"
			    exit 1
			fi
                        basename=`basename $file`
                        fileName="${basename%.*}"
                        fileExt="${basename##*.}"
                        case $fileExt in
                            exe|EXE)
                                biosPath=`dirname $file`
                                biosFile=$file
                                biosName=$(basename $file)
				shortBiosName=$(shortname $biosName)
                                ;;
                            *)
                                echo "Error: $file must end in .exe"
                                showUsage
                                exit 1
                                ;;
                            esac
                    fi
                else
                    echo "Error: $0 does not take \"$1\" as an option"
                    showUsage
                    exit 1
                fi
               ;;
        esac
    fi
    shift
done

if [ -z $file ]; then
    echo "Error: must enter filename"
    showUsage
    exit 1
fi

if [ -z "$destination" ]; then
    destination=$tmpPath/$fileName.iso
fi
if [ "$installFlag" == 1 ] || [ "$uninstallFlag" == 1 ]; then
    test_root
fi

if [ "$uninstallFlag" == 1 ]; then
    uninstall
fi

if [ "$mkImgFlag" == 1 ] && [ "$imgCompleteFlag" == 0 ]; then
    makeImage
fi

if [ "$installFlag" == 1 ]; then
    install
fi
