#! /bin/bash

clear
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "         The makeGRUB script to create GRUB boot files - TeraByte, Inc"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo

# check running as root
userid=`id -u`
if [ ! "$userid" = "0" ]; then
    echo "This script must be run as root...exiting"
    echo
    exit 1
fi
# get directory owner and group
currentdir=`pwd`
ownerid=`stat -c %U $currentdir`
groupid=`stat -c %G $currentdir`
if [ "$currentdir" = "/" ]; then
    echo "This script cannot be run from the / directory...exiting"
    echo
    exit 1
fi

# check for read/write access and running on Linux fs
tf1=0;tf2=0
for i in `seq 1 5000`
do
    if [ "$tf1" = "0" ]; then
        if [ ! -f t$i ] && [ ! -d t$i ]; then tf1=t$i; fi
    elif [ "$tf2" = "0" ]; then
        if [ ! -f t$i ] && [ ! -d t$i ]; then tf2=t$i; fi
    else
        break
    fi
done
if [ ! "$tf1" = "0" ] && [ ! "$tf2" = "0" ]; then
    touch $tf1 2> /dev/null
    if [ ! -e $tf1 ]; then
        echo "Unable to create a test file. This indicates that this partition"
        echo "is mounted read only. To work with the IFL disk from Linux, the"
        echo "zip archive must be extracted on a *Linux* partition, and that"
        echo "partition must be mounted with read/write privileges...exiting"
        echo
        exit 1
    fi
    chmod +x $tf1
    chmod -x $tf1
    cp $tf1 $tf2
    if [ -x $tf2 ]; then
        rm $tf1; rm $tf2
        echo "This script must be run on a Linux file system. It appears to be"
        echo "either FAT/FAT32 or NTFS. Please extract the IFL zip archive on"
        echo "a Linux partition (ext2/3 or reiserfs)...exiting"
        echo
        exit 1
    fi
    rm $tf1; rm $tf2
fi

# parse command line
if [ "$1" = "/c" ] && [ "$2" = "" ]; then 
    custom=1
elif [ "$1" = "" ] && [ "$2" = "" ] ; then
    custom=0
else # show usage if command line error
    echo "Command line entered: $0 $1 $2 $3 $4"
    echo
    echo "Usage:  ./makeGRUB [/c]"
    echo "  /c  - create custom configuration based on config.txt, ifl.ini, and the"
    echo "        scripts, wireless, and iscsi directories"
    echo
    echo "Usage examples:"
    echo "./makeGRUB /c   -> create custom configuration"
    echo "./makeGRUB      -> create default configuration"
    echo
    echo "Note that without the /c option, makeGRUB will create the GRUB boot files"
    echo "based on the default configuration (same as iflnet.iso)."
    echo
    exit 1
fi

echo "Checking for required files and directories..."
m=0
if [ ! -e iflnet.iso ] && [ ! -e IFLNET.ISO ]; then
    m=1
    echo "File iflnet.iso (or IFLNET.ISO) not found"
else
    if [ -e iflnet.iso ]; then 
	isofile=iflnet.iso
    else
	isofile=IFLNET.ISO
    fi
fi
if [ ! -d util ]; then
    m=1
    echo "Directory util was not found, or is not a directory"
fi
if [ ! -x util/cpio ]; then
    m=1
    echo "File util/cpio was not found, or is not exeutable"
fi
if [ ! -e config.txt ] && [ "$custom" = "1" ]; then
    m=1
    echo "Required file config.txt not found"
fi
if [ "$m" = "0" ]
    then
    echo "All required files and directories found"
else
    echo
    echo "One or more required files or directories were not found"
    echo "See above messages for details...exiting script"
    echo
    exit 1
fi


# clean up from possible failed run (normally not needed)
# probably need a couple more checks here
if [ -e build-tmp ]
    then rm -r build-tmp
fi

# clean up existing grub dirextory (if any), create new one
# copy files from util directory
echo "Deleting any previous contents of grub directory"
rm -r grub 2> /dev/null
mkdir grub

# mount the default iflnet.iso file to get files from it
# echo "Creating temp directory structure, and loop mounting $isofile"
mkdir build-tmp
cd build-tmp
mkdir isomount
mount -t iso9660 -o loop ../$isofile isomount

if [ "$custom" = "0" ]; then
    echo "Building default configuration"
    echo "Copying required files to the grub directory"
    cp -a isomount/vmlinuz ../grub/vmlinuz
    cp -a isomount/initrmfs.gz ../grub/initrmfs.gz
    # get the Product Key from isolinux.cfg
    ProductKeySearch=`grep -o -m1 ProductKey=.............. isomount/isolinux.cfg`
    CurrentProductKey=`echo ${ProductKeySearch:11}`
    ProductKeyText="ProductKey=$CurrentProductKey"
    umount isomount
else ##################################################################

echo "Building custom configuration (/c option was used)"
mkdir cdroot
# echo "Copying contents of $isofile to build directory"
cp -a isomount/* cdroot/
umount isomount

# decompress and extract root file system so that changes can be made
mkdir initrmfs
echo "Decompressing and extracting the root filesystem"
gunzip cdroot/initrmfs.gz
cd initrmfs
../../util/cpio -i -m -d < ../cdroot/initrmfs
cd ..

# get the Product Key from isolinux.cfg
ProductKeySearch=`grep -o -m1 ProductKey=.............. cdroot/isolinux.cfg`
CurrentProductKey=`echo ${ProductKeySearch:11}`
ProductKeyText="ProductKey=$CurrentProductKey"

# source config.txt to get options - make sure it's a unix text file
../util/fromdos ../config.txt
. ../config.txt

# get settings from saved values if any
if [ -d ../util/settings ]; then
    cp -a ../util/settings/* initrmfs/tbu/utility 2> /dev/null
else
    mkdir ../util/settings
fi

detect_swraid_arrays() {
    swraidfile="initrmfs/etc/mdadm/swraid.log"
    rm initrmfs/etc/mdadm/mdadm.conf 2> /dev/null
    rm initrmfs/etc/mdadm/mdnames.conf 2> /dev/null
    echo "Analyzing software RAID configuration on this system..." > $swraidfile
    while [ 0 ]; do
        mdadmpath=`which mdadm` > /dev/null
        if [ ! "$?" = "0" ]; then
            echo "The mdadm program was not detected." >> $swraidfile
            break
        elif [ ! -r /proc/mdstat ]; then
            echo "Software RAID driver(s) not loaded (no /proc/mdstat)" >> $swraidfile
            break
        else
            mdarrays=( $(mdadm -D --scan) )
            sizemdarrays=${#mdarrays[@]}
            narrays=`mdadm -D --scan | grep -c ARRAY` > /dev/null
            if [ "$sizemdarrays" = "0" ] || [ "$narrays" = "0" ]; then
                echo "No array(s) currently running" >> $swraidfile
                break
            elif [ ! "${mdarrays[0]}" = "ARRAY" ]; then
                echo "No array(s) currently running" >> $swraidfile
                break
            fi
        fi

        # have at least 1 array running
        let mdarraysloop=sizemdarrays-1
        nvalidarrays=0
        nebitmaps=0
        for i in `seq 0 $mdarraysloop`
        do
            let j=i+1
            if [ "${mdarrays[$i]}" = "ARRAY" ]; then
                array[0]=${mdarrays[$i]}
                arrayindex=0
                validarray=1
            elif [ "$arrayindex" = "0" ]; then
                array[1]=${mdarrays[$i]}
                arraydevice=`file -L ${mdarrays[$i]} | grep \(9/`
                if [ "$arraydevice" = "" ]; then  # not 9 major means partitioned
                   array[2]="auto=mdp15"
                    arrayindex=2
                    arrayname=${mdarrays[$i]:5}
                    ebitmap=`grep -A3 $arrayname /proc/mdstat | grep bitmap: | grep file:`
                    if [ ! "$ebitmap" = "" ]; then
                        validarray=0
                        let nebitmaps=nebitmaps+1
                        echo "Array $arrayname NOT compatible (is using external bitmap file)" >> $swraidfile
                    else
                        echo "Array $arrayname is compatible" >> $swraidfile
                    fi
                else                            # 9 major means non-partitioned array
                    array[1]=${mdarrays[$i]}
                    arrayindex=1
                    arrayname=${mdarrays[$i]:5}
                    ebitmap=`grep -A3 $arrayname /proc/mdstat | grep bitmap: | grep file:`
                    if [ ! "$ebitmap" = "" ]; then
                        validarray=0
                        let nebitmaps=nebitmaps+1
                        echo "Array $arrayname NOT compatible (using external bitmap file)" >> $swraidfile
                    else
                        echo "Array $arrayname is compatible" >> $swraidfile
                    fi
               fi
            else
                let arrayindex=arrayindex+1
                array[$arrayindex]=${mdarrays[$i]}
            fi

            if [ "${mdarrays[$j]}" = "ARRAY" ] || [ "$j" = "$sizemdarrays" ] ; then
                if [ "$validarray" = "1" ]; then
                    validarraynames[$nvalidarrays]=$arrayname
                    let nvalidarrays=nvalidarrays+1
                    for k in `seq 0 $arrayindex`
                    do
                        if [ "$k" = "0" ] && [ "$nvalidarrays" = "1" ]; then
                            if [ ! -d initrmfs/etc/mdadm ]; then mkdir initrmfs/etc/mdadm; fi
                            # The line below supposedly causes mdadm to search all devices listed
                            # in /proc/partitions including whole drives
                            echo "DEVICE partitions" > initrmfs/etc/mdadm/mdadm.conf
                            # The line below may not be needed, but it doesn't hurt
                            # Devices seem to get created the same with or without it
                            echo "CREATE auto=yes" >> initrmfs/etc/mdadm/mdadm.conf
                        fi
                        if [ "$k" = "$arrayindex" ]; then
                            echo ${array[$k]} >> initrmfs/etc/mdadm/mdadm.conf
                            break
                        else
                            echo -n "${array[$k]} " >> initrmfs/etc/mdadm/mdadm.conf
                        fi
                    done
                fi

            fi
            if [ "$j" = "$sizemdarrays" ] ; then break; fi
        done
        if [ ! "$nvalidarrays" = "0" ]; then
            # echo "n ebitmaps detected = $nebitmaps"
            nebitmapsmdstat=`grep bitmap: /proc/mdstat | grep -c file:`
            # echo "n ebitmaps in mdstat = $nebitmapsmdstat"
            nbitmapsmdadm=`mdadm -Dsvv | grep -c "Intent Bitmap"`
            # echo "n bitmaps in mdadm = $nbitmapsmdadm"
            nintbitmapsmdadm=`mdadm -Dsvv | grep -c "Intent Bitmap : Internal"`
            # echo "n internal bitmaps in mdadm = $nintbitmapsmdadm"
            let nebitmapsmdadm=nbitmapsmdadm-nintbitmapsmdadm
            # echo "n ebitmaps in mdadm = $nebitmapsmdadm"
            # make sure no mistake in detecting external bitmap files
            # if there is, delete the config file
            if [ ! "$nebitmaps" = "$nebitmapsmdstat" ]; then
                echo "External bitmap error 1" >> $swraidfile
                rm initrmfs/etc/mdadm/mdadm.conf 2> /dev/null
                break
            elif [ ! "$nebitmaps" = "$nebitmapsmdadm" ]; then
                echo "External bitmap error 2" >> $swraidfile
                rm initrmfs/etc/mdadm/mdadm.conf 2> /dev/null
                break
            fi
        fi
        if [ "$nvalidarrays" = "0" ]; then
            echo "No compatible software RAID arrays were detected" >> $swraidfile
            break
        else
            echo ${validarraynames[@]} > initrmfs/etc/mdadm/mdnames
            echo "$nvalidarrays compatible software RAID array(s) detected" >> $swraidfile
        fi
        break
    done
}

# call swraid detect function
if [ ! -e initrmfs/tbu/utility/nsr ]; then
    detect_swraid_arrays
fi

# call settings menu
chroot initrmfs /usr/bin/custom-menu

# call restore disc menu
#chroot initrmfs /usr/bin/restore-menu

# save settings and clean up root fs
if [ ! -e initrmfs/tbu/utility/md ]; then
    if [ -e initrmfs/tbu/utility/rdmd ]; then
        rdmd=`cat initrmfs/tbu/utility/rdmd`
        if [ "$rdmd" = "0" ]; then
            rm initrmfs/etc/mdadm/* 2> /dev/null
        fi
    else
        rm initrmfs/etc/mdadm/* 2> /dev/null
    fi
fi
for i in iflkmap ktl vga boot lvm md rdiflkmap rdktl rdvga rdboot rdcmd rdlvm rdmd
do
    if [ -e initrmfs/tbu/utility/$i ]; then
	cp -a initrmfs/tbu/utility/$i ../util/settings/$i
    else
	rm ../util/settings/$i 2> /dev/null
    fi
done
for i in iflkmap ktl vga 
do
    if [ -e initrmfs/tbu/utility/$i ]; then
	rm initrmfs/tbu/utility/$i 2> /dev/null
    fi
done

# get variables for config files
# keyboard
if [ -e ../util/settings/iflkmap ]; then
    kbd=`cat ../util/settings/iflkmap`
    ktl=`cat ../util/settings/ktl`
else
    kbd=us
    ktl=qwerty
fi
# video
if [ -e ../util/settings/vga ]; then
    vmode=`cat ../util/settings/vga`
else
    vmode=0
fi    
# boot parameters
if [ -e ../util/settings/boot ]; then
    bootparms=`cat ../util/settings/boot`
else
    bootparms=""
fi

clear
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "         The makeGRUB script to create GRUB boot files - TeraByte, Inc"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo
echo "OPTION 1: Settings menu"
echo

# prompt for console login option
echo "OPTION 2: Do you want a console login to be required (default is No)?"
echo "Enter y and press <Enter> for Yes"
echo -n "Just press <Enter> for No  "
yn=0
dologin=n
read yn
if [ "$yn" = "y" ] || [ "$yn" = "Y" ]; then
    dologin=y
else
    dologin=n
fi
if [ "$dologin" = "y" ]; then
    echo "Console login will be required"
    echo "Note: The default root password is 'ifl'"
else
    echo "Console login will not be required on boot (default)"
fi

# prompt for password change option
echo
echo "OPTION 3: Change root password from the default of 'ifl'?"
echo "Enter y and press <Enter> for Yes"
echo -n "Just press <Enter> for No  "
yn=0
password=n
read yn
if [ "$yn" = "y" ] || [ "$yn" = "Y" ]; then
    password=y
else
    password=n
fi
if [ "$password" = "y" ]; then
    echo "The default root password will be changed"
else
    echo "The default root password will be used"
fi
echo

# copy files and directories to root file system
if [ -e ../ifl-custom.ini ]; then
    echo "Copying ifl-custom.ini to the root filesystem as ifl.ini"
    cp -a ../ifl-custom.ini initrmfs/tbu/ifl.ini
    chown 0:0 initrmfs/tbu/ifl.ini
elif [ -e ../IFL.INI ]; then
    echo "Copying IFL.INI to the root filesystem"
    cp -a ../IFL.INI initrmfs/tbu/IFL.INI
    chown 0:0 initrmfs/tbu/IFL.INI
fi

if [ -e ../config.txt ]; then
    echo "Copying config.txt to the root filesystem"
    cp -a ../config.txt initrmfs/etc/config.txt
    chown 0:0 initrmfs/etc/config.txt
elif [ -e ../CONFIG.TXT ]; then
    echo "Copying CONFIG.TXT to the root filesystem"
    cp -a ../CONFIG.TXT initrmfs/etc/config.txt
    chown 0:0 initrmfs/etc/config.txt
fi

if [ -e ../scripts ]; then
    echo "Copying scripts directory to the root filesystem"
    cp -a ../scripts initrmfs/tbu/scripts
    chown -R 0:0 initrmfs/tbu/scripts/
elif [ -e ../SCRIPTS ]; then
    echo "Copying SCRIPTS directory to the root filesystem"
    cp -a ../SCRIPTS initrmfs/tbu/scripts
    chown -R 0:0 initrmfs/tbu/scripts/
fi

if [ -e ../wireless ]; then
    echo "Copying wireless directory to the root filesystem"
    cp -a ../wireless/ndiswrapper initrmfs/tbu/ndiswrapper
    cp -a ../wireless/network-profiles initrmfs/etc/network-profiles
    chown -R 0:0 initrmfs/tbu/ndiswrapper/
    chown -R 0:0 initrmfs/etc/network-profiles/
    if [ -e ../wireless/wpa_supplicant.conf ]; then
        cp -a ../wireless/wpa_supplicant.conf initrmfs/etc
        chown 0:0 initrmfs/etc/wpa_supplicant.conf
    fi
fi

if [ -e ../iscsi ]; then
    echo "Copying iscsi directory to the root filesystem"
    rm -r initrmfs/etc/iscsi
    cp -a ../iscsi initrmfs/etc/iscsi
    cp -a ../help/iscsi.txt initrmfs/etc/iscsi/iscsi.txt
    ../util/fromdos initrmfs/etc/iscsi/iscsi.txt
    chown -R 0:0 initrmfs/etc/iscsi/
fi

# if console login option selected, switch /etc/inittab file
if [ "$dologin" = "y" ]; then
    echo "For OPTION 2: Configuring root filesystem to require console login"
    cp -a initrmfs/etc/inittab-getty initrmfs/etc/inittab
fi

# if password option selected, chroot into root file system to make the change
if [ "$password" = "y" ]; then
    echo "For OPTION 3: You will now be prompted to enter a new root password"
    echo "Password can be ANY string of 1 to 8 characters"
    ps=0
    while [ "$ps" = "0" ]
    do
        chroot initrmfs /usr/bin/passwd
        if [ "$?" = "0" ]; then
            ps=1
        else
            echo "Error while changing password...please try again"
        fi
    done
fi

# run getty on one or both serial ports, based on config.txt
if [ "$SERIAL_PORTS" = "1" ]; then
    echo "ttyS0::respawn:-/sbin/getty -L ttyS0 9600 vt100" >> initrmfs/etc/inittab
elif [ "$SERIAL_PORTS" = "2" ]; then
    echo "ttyS1::respawn:-/sbin/getty -L ttyS1 9600 vt100" >> initrmfs/etc/inittab
elif [ "$SERIAL_PORTS" = "B" ]; then
    echo "ttyS0::respawn:-/sbin/getty -L ttyS0 9600 vt100" >> initrmfs/etc/inittab
    echo "ttyS1::respawn:-/sbin/getty -L ttyS1 9600 vt100" >> initrmfs/etc/inittab
fi

# recompress the root file system
cd initrmfs
echo "Recompressing the root filesystem...please wait"
find . -print | ../../util/cpio -o -a -H newc > ../cdroot/initrmfs
cd ..
gzip -9 cdroot/initrmfs

# copy kernel, initrmfs.gz, and ktl files to the hdd directory
# menu.txt and boot loader config file are already there
echo "Copying required files to the grub directory"
cp -a cdroot/vmlinuz ../grub/vmlinuz
cp -a cdroot/initrmfs.gz ../grub/initrmfs.gz
fi ##############################################################################

# unmount and clean up
# echo "Cleaning up temporary directories and files..."
cd ..
rm -r build-tmp
chmod -R +w grub

mountpoint /boot > /dev/null 2>&1
if [ "$?" = "0" ]; then bootpath=/ifl; else bootpath=/boot/ifl; fi
    
# build menu.lst boot stanza file for GRUB
if [ "$custom" = "0" ]; then
    echo "kernel         $bootpath/vmlinuz vga=0 iflkmap=us ktl=qwerty $ProductKeyText" > grub/ifl-menu.lst
else
    echo "kernel         $bootpath/vmlinuz vga=$vmode iflkmap=$kbd ktl=$ktl $ProductKeyText $bootparms" > grub/ifl-menu.lst
fi

# chown all files and directories to owner:group
# as precaution make sure running from IFL dir, otherwise don't do it
if [ "$0" = "./makeGRUB" ]; then
    chown -R $ownerid:$groupid util 2> /dev/null
    chown -R $ownerid:$groupid help 2> /dev/null
    chown -R $ownerid:$groupid wireless 2> /dev/null
    chown -R $ownerid:$groupid scripts 2> /dev/null
    chown -R $ownerid:$groupid iscsi 2> /dev/null
    chown -R $ownerid:$groupid cdboot 2> /dev/null
    chown -R $ownerid:$groupid pxe 2> /dev/null
    chown -R $ownerid:$groupid grub 2> /dev/null
    chown $ownerid:$groupid *
fi

echo
echo "The build of the GRUB boot files is now complete"
echo "The files required for GRUB boot can be found in the grub directory"
echo
