#!/bin/bash 

## -----------------------------------------------------------------------
##  $Id: mkusb,v 0.1 2006/22/01 17:36:00 MaxMan Exp $
##   
##   Copyright 2006-2007 Massimo Mancini - All Rights Reserved
##
##   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, Inc., 53 Temple Place Ste 330,
##   Boston MA 02111-1307, USA; either version 2 of the License, or
##   (at your option) any later version; incorporated herein by reference.
##
## -----------------------------------------------------------------------

function query_for_removable () {
    cd /sys/block
    grep -l 1 sd*/removable| sed 's!/removable!!'
}
function cleanup () {
    umount -d $ISO_MNT_POINT 2> /dev/null
    [ -d $ISO_MNT_POINT ] && rmdir $ISO_MNT_POINT 2> /dev/null
}
function eco() {
    ESC="\033["
    RED="${ESC}31;1m"
    BLUE="${ESC}34;1m"
    GREEN="${ESC}44;33;1m"
    NOR="${ESC}0m"
    local col=$1
    shift
    if [ "$col" = g ] ; then
        COL=$GREEN
    elif
        [ "$col" = r ] ; then
        COL=$RED
    elif
        [ "$col" = b ] ; then
        COL=$BLUE
    fi
    echo -e ${COL}$*$NOR
}
function check_device(){
    if [ -L /dev/$DEVUSB -o -b /dev/$DEVUSB ]; then
        DEVREMV="/sys/block/$DEVUSB/removable"
        # ls -lt $DEVREMV
        if [ -f $DEVREMV ] ; then
            REMOVABLE=$(cat $DEVREMV)
            if [ "$REMOVABLE" != "1" ]; then
                eco r "ERRORE: $DEVUSB non è un dispositivo rimovibile - removable = $REMOVABLE"
                exit
            fi   
        else
            eco r "ERRORE: $DEVUSB non è un dispositivo rimovibile"
            exit
        fi   
        eco b "device OK: /dev/$DEVUSB"
    else
        eco r "ERRORE: DISPOSITIVO /dev/$DEVUSB NON TROVATO"
        ls -lt /dev/sd*
        exit
    fi	
}
function wait_for_usb () {
    DEVREMV="/sys/block/$DEVUSB/removable"
    for i in 1 2 3 4 5 6 7 8 ; do
        if [ -f $DEVREMV ] ; then eco g "TROVATO $DEVREMV";return ; fi
        eco r "sto cercando lo stick, attendi $i..."
        sleep $i
    done
    eco r "ERRORE FATALE - stick USB non trovato"
    exit
}
function wait_for_usbpart () {
    for i in 1 2 3 4 5 6 7 8 ; do
        if [ -L $USBPART -o -b $USBPART ] ; then 
            eco g "TROVATO $USBPART"
            return  
        fi
        eco r "sto cercando $USBPART, attendi $i..."
        sleep $i
    done
    eco r "ERRORE FATALE - $USBPART non trovato"
    exit
}
function togli_e_metti (){
    eco r   "*****************************************************"
    read -p "ATTENZIONE: togli e rimetti lo stick poi premi INVIO"
    wait_for_usb
}	
function zap_usb () {
    eco b "dd if=/dev/zero of=/dev/$DEVUSB bs=512 count=100"
    dd if=/dev/zero of=/dev/$DEVUSB bs=512 count=100
}
function format_usb_hdg () {
    eco b "Attendi, preparazione USB-HDD con GRUB..."
    DEVPART=1
    GRUBROOT="(hd0,0)"
    # descrizione delle partizioni ottenute via sfdisk
    SFDISK1=",,6,*"
    SFDISK2=";"
    SFDISK3=";"
    SFDISK4=";"
    USBPART=/dev/$DEVUSB$DEVPART
    if [ "$ALTERGEO" = "SI" ] ; then
        GEOM="-H 255 -S 63"
    else
        GEOM=""
        [ ! -z $C ] && GEOM="$GEOM -C $C"
        [ ! -z $H ] && GEOM="$GEOM -H $H"
        [ ! -z $S ] && GEOM="$GEOM -S $S"
    fi    
    sfdisk --DOS  $GEOM /dev/$DEVUSB <<EOF
$SFDISK1
$SFDISK2
$SFDISK3
$SFDISK4
EOF
    eco b "azzero il primo settore di $USBPART"
    dd if=/dev/zero of=$USBPART bs=512 count=1
    sync
# 	togli_e_metti 
    wait_for_usbpart
    eco b "creo un filesystem DOS"
    mkdosfs $USBPART
# 	togli_e_metti
    copia_iso
    if [ $INSTMBR -eq 1 ]; then
        eco b "installo MBR: install-mbr -e 1 /dev/$DEVUSB"
        install-mbr -e 1 /dev/$DEVUSB
    fi	
    setup_bootloader_grub
}
function format_usb_hds () {
    eco b "Attendi, preparazione USB-HDD con SYSLINUX..."
    DEVPART=1
    # parametri mkdiskimage
    OPT=""
    
    GEOM="0 255 63"
    if [ ! -z $H ] ; then
        if [ ! -z $S ] ; then
            [ ! -z $C ] && GEOM="$C " || GEOM="0 "
            [ ! -z $H ] && GEOM="$H "
            [ ! -z $S ] && GEOM="$S"
        fi    
    fi    
    
    USBPART=/dev/$DEVUSB$DEVPART
    [ ! -f /usr/bin/mkdiskimage ] && eco r "ERRORE: non trovo mkdiskimage" && help
    eco b "mkdiskimage $OPT /dev/$DEVUSB $GEOM"
    mkdiskimage $OPT /dev/$DEVUSB $GEOM
    togli_e_metti
    copia_iso
    setup_bootloader_sys
}
function format_usb_zip () {
    eco b "Attendi, formattazione USB-ZIP in corso..."
    DEVPART=4
    GRUBPART="(hd0,3)"
    # parametri mkdiskimage
    OPT="-4"
    GEOM="0 64 32"
    USBPART=/dev/$DEVUSB$DEVPART
    if [ $BOOTLDR = 'sys' ]; then
        [ ! -f /usr/bin/mkdiskimage ] && eco r "ERRORE: non trovo mkdiskimage" && help
        eco  "mkdiskimage $OPT /dev/$DEVUSB $GEOM"
        mkdiskimage $OPT /dev/$DEVUSB $GEOM
        # 	togli_e_metti
        copia_iso
        setup_bootloader_sys
    else
        SFDISK1="0,0,,"
        SFDISK2="0,0,,"
        SFDISK3="0,0,,"
        SFDISK4=",,6,*"
        sfdisk --DOS  -H 64 -S 32 /dev/$DEVUSB <<EOF
$SFDISK1
$SFDISK2
$SFDISK3
$SFDISK4
EOF
        eco b "azzero il primo settore di $USBPART"
        dd if=/dev/zero of=$USBPART bs=512 count=1
        sync
    # 	togli_e_metti 
        wait_for_usbpart
        eco b "creo un filesystem DOS"
        mkdosfs $USBPART
    # 	togli_e_metti
        copia_iso
        if [ $INSTMBR -eq 1 ]; then
            eco b "installo MBR: install-mbr -e 4 /dev/$DEVUSB"
            install-mbr -e 4 /dev/$DEVUSB
        fi	
        setup_bootloader_grub
    fi    
}
function copia_iso () {
    # trasferimento della iso
    [ -z $USBPART ] && eco r "ERRORE FATALE: qualcosa è andato storto" && exit
    eco b "trasferisco la iso..."
    mkdir $MNTUSB 2>/dev/null
    wait_for_usbpart
    
    eco b "mount $USBPART $MNTUSB"
    if ! mount $USBPART $MNTUSB ; then eco r "OPERAZIONE FALLITA" ; exit ; fi
    
    cp -ra $ISO_MNT_POINT/* $MNTUSB
#    umount $ISO_MNT_POINT
#    rm -fr $ISO_MNT_POINT
    eco b "cd $MNTUSB"
    cd $MNTUSB
    rm isolinux.cfg*
    rm make_iso*
# 	sync
}
function setup_bootloader_sys () {
    eco b "installo SYSLINUX"
    cat <<TXT > ./syslinux.cfg
display splash.cfg
default linux
prompt 1
timeout 40
F1 boot/splash.txt
F2 boot/splash.cfg

label linux
kernel vmlinuz
append max_loop=255 initrd=initrd.gz init=linuxrc load_ramdisk=1 prompt_ramdisk=0 ramdisk_size=8000 root=/dev/ram0 rw $CONF $DEBUG

label conf
kernel vmlinuz
append max_loop=255 initrd=initrd.gz init=linuxrc load_ramdisk=1 prompt_ramdisk=0 ramdisk_size=8000 root=/dev/ram0 rw conf

label noconf
kernel vmlinuz
append max_loop=255 initrd=initrd.gz init=linuxrc load_ramdisk=1 prompt_ramdisk=0 ramdisk_size=8000 root=/dev/ram0 rw nofloppy nousb

label memtest
kernel boot/memtest
TXT
    cp boot/vmlinuz .
    cp boot/initrd.gz .
    cd /
    ls -lt $MNTUSB
    umount $MNTUSB
    eco b syslinux $SLOW $USBPART
    syslinux $SLOW $USBPART
    rm -fr $MNTUSB
    eco b "controlli post-installazione"
    eco b "sfdisk..."
    sfdisk -l /dev/$DEVUSB
}
function setup_bootloader_grub () {
    eco b "installo GRUB..."
    eco b "genero /boot/grub/menu.lst"
    #perl  -pe '{$_ =~ s/\(cd\)/\(hd0,0\)/ }' /tmp/sdc/boot/grub/menu.lst
    perl -i -pe '{$_ =~ s/\(cd\)/\(hd0,0\)/}' ./boot/grub/menu.lst
#     cat <<TXT > ./boot/grub/menu.lst
# default		0
# #splashimage (cd)/boot/pinguino2.xpm.gz
# timeout		5
# color cyan/blue white/blue

# title		Debian GNU/Linux, kernel 2.6.12.4sd 
# root		$GRUBROOT
# kernel		/boot/vmlinuz root=/dev/ram0 rw init=/linuxrc $CONF $DEBUG
# initrd		/boot/initrd.gz
# boot

# title		Debian GNU/Linux, kernel 2.6.12.4sd con occhiali
# root		$GRUBROOT
# kernel		/boot/vmlinuz root=/dev/ram0 rw init=/linuxrc vga=791 $CONF $DEBUG
# initrd		/boot/initrd.gz
# boot

# title Memtest
# kernel /boot/memtest

# title           help
# root		$GRUBROOT
# cat		/boot/info.txt
# TXT


    
    eco b "adesso installo GRUB...porta pazienza, non sarò rapido ;-)"
    
grub --batch <<EOT
device (hd7) /dev/$DEVUSB
root $GRUBR
setup $GRUBS
quit
EOT

    eco b "controlli post-installazione"
    eco b "sfdisk..."
    sfdisk -l /dev/$DEVUSB
    eco b "grub...."
grub --batch <<EOT>/tmp/grub.esito
device (hd7) /dev/$DEVUSB
geometry (hd7)
quit
EOT

if grep -i "Filesystem type is fat" /tmp/grub.esito ; then
    eco b "ESITO: sei stato fortunato, forse va ;-)"
else
    eco r "ESITO: certamente non funzionerà, tenta ancora :-("
fi	
}
function termina () {
    # cleanup now accomplished by 'trap cleanup EXIT'

#     cd /tmp
#     eco b "umount $MNTUSB"
#     umount $MNTUSB
    eco b "+++++ OPERAZIONE TERMINATA +++++"
}
function help(){
eco r $ERRMSG
cat <<TXT
===========================================================
MkUsb - ver.0.1 - by MaxMan - ARGOLIVE USB Installer
===========================================================
USO: mkusb [-C cil] [-H head] -[S sect] [-i distro] [-g] \
            [-b hdd|zip] [-l grub|sys] [-p mbr|pbr] \
            [-c] [-d] device

device      sda | sdb | /dev/sda |/dev/sdb ecc.ecc.
            il device deve essere rimovibile

    -C      cilindri (se omesso viene calcolato)
    -H      head (max 255)
    -S      settori (max 63)                      
    -g      altera la geometria dello stick in modo standard
            USB-HDD -> C=calcolati, H=255, S=63
            USB-ZIP -> C=calcolati, H=64, S=32

    -i distro [default=/misc/distro/livecd.iso]
       altro file iso
       cartella contenente la iso (es. BootLive)
    
    -b hdd|zip     modo BIOS di lettura dello stick [hdd]
    -l grub|sys    (loader) installa GRUB o SYSLINUX [grub] 
    
    -p mbr|pbr     scelta del settore di boot  [mbr]
    -c     scelta interattiva della conf. [scelta automatica]
    -d     attiva modo debug [debug disattivato]                            
    -s     installa SYSLINUX con l'opzione -s
    -q     scrive i device removable presenti nel sistema ed esce
-----------------------------------------------------------
Sono necessarie le seguenti utilities:
per il boot in modo ZIP,HDS : mkdiskimage, syslinux
per il boot in modo HDD+GRUB MBR: sfdisk 
per il boot in modo HDD+GRUB PBR: sfdisk, install-mbr
-----------------------------------------------------------
MBR = Master Boot Record
PBR = Partition Boot Record (grub è installato all'
inizio della partizione anziche del disco)
===========================================================
TXT
eco r $ERRMSG
exit
}

### PROGRAM
ISO=/misc/distro/livecd.iso
BOOTMODE='hdd'    # hdd|zip
BOOTLDR='grub'    # grub|syslinux
BOOTFROM='mbr'    # mbr|pbr
ALTERGEO='NO'     # altera la geometria in modo prefissato
ISO_MNT_POINT=$(mktemp -d)
CONF=''
DEBUG=''
SLOW=''
[ -f ~/.mkusbrc ] && source ~/.mkusbrc

while getopts qC:H:S:i:b:l:p:hgcds var ; do
    case $var in
        h)  help; exit
        ;;
        C) C=$OPTARG
        ;;
        H) H=$OPTARG
        ;;
        S) S=$OPTARG
        ;;
        i) ISO=$OPTARG
        ;;
        b) BOOTMODE=$OPTARG
        ;;
        l) BOOTLDR=$OPTARG
        ;;
        p) BOOTFROM=$OPTARG
        ;;
        g) ALTERGEO='SI'
        ;;
        c) CONF='conf'
        ;;
        d) DEBUG='debug'
        ;;
        s) SLOW='- s'
        ;;
	q) query_for_removable
	   exit
	    ;;
    esac
done
shift ` expr $OPTIND - 1 `


case $BOOTMODE in
    hdd)
        case $BOOTLDR in
            grub) 
                case $BOOTFROM in
                    mbr) TIPOBOOT='hdg' ; INSTMBR=0 ;;
                    pbr) TIPOBOOT='hdg' ; INSTMBR=1 ;;
                    *) BOOTFROM='' ;;
                esac
                ;;
            sys) 
                ALTERGEO='SI'
                case $BOOTFROM in
                    mbr) TIPOBOOT='hds' ;;
                    *) BOOTFROM='' ;;
                esac
                ;;
        esac   
        ;;
    zip)
        ALTERGEO='SI'
        case $BOOTLDR in
            grub) 
                case $BOOTFROM in
                    mbr) TIPOBOOT='zip' ; INSTMBR=0 ;;
                    pbr) TIPOBOOT='zip' ; INSTMBR=1 ;;
                    *) BOOTFROM='' ;;
                esac
            ;;
            sys)
                case $BOOTFROM in
                    mbr) TIPOBOOT='zip' ;;
                    *) BOOTFROM='' ;;
                esac
            ;;
        esac
    ;;
esac    

if [ -z $BOOTFROM -o -z $TIPOBOOT ] ; then
    ERRMSG='ERRORE opzioni errate'
    help
fi

[ -z $1 -a -z "$DEVUSB" ] && ERRMSG='devi indicare il device USB' && help
#[ -z "$DEVUSB" ] && 
DEVUSB=$(echo $1 | sed 's/\/dev\///g')

MNTUSB=/tmp/$DEVUSB
USBPART=""


# check file iso o cartella contenente la distro
if [ -d $ISO ] ; then
    if [ ! -f $ISO/boot/grub/stage1 ] ; then
	ERRMSG="ERRORE: non trovo $ISO/boot/grub/stage1 - $ISO contiene la distro ???"
	help
    fi
elif [ -f $ISO ] ; then
    #eco b "mount -o loop $ISO $ISO_MNT_POINT"
    mkdir $ISO_MNT_POINT 2>/dev/null
    if ! mount -o loop $ISO $ISO_MNT_POINT ; then
	eco r "OPERAZIONE FALLITA: mount -o loop $ISO $ISO_MNT_POINT" 
	exit 
    fi
fi    

# parametri di installazione di GRUB
if [ $INSTMBR -eq 1 ]; then
    if [ $BOOTMODE = 'hdd' ] ; then
        GRUBR='(hd7,0)' 
        GRUBS='(hd7,0)' 
    else 
        GRUBR='(hd7,3)' 
        GRUBS='(hd7,3)'
    fi
else    
    if [ $BOOTMODE = 'hdd' ] ; then
        GRUBR='(hd7,0)' 
    else #zip
        GRUBR='(hd7,3)' 
    fi            
    GRUBS='(hd7)'
fi	

[ $BOOTLDR = "grub" ] && SETGRUB="root $GRUBR - setup $GRUBS" || SETGRUB=''

# ... si puo' iniziare ;-)

eco b "========================================================="
eco b " MkUsb 0.1 - by MaxMan - ARGOLIVE USB Installer" 
eco b "========================================================="

cat <<TXT
autoconfigurazione........: $CONF
debug attivato............: $DEBUG
iso.......................: $ISO
device....................: /dev/$DEVUSB
punto di mount............: $MNTUSB
modo di boot del bios.....: $BOOTMODE 
bootloader................: $BOOTLDR  $SETGRUB $SLOW
posizione di installazione: $BOOTFROM
geometria standard imposta: $ALTERGEO
geometria qualsiasi C,H,S.: C:$C H:$H S:$S
---------------------------------------------------------
TXT
eco r "ENTER per confermare  ^C per interrompere"
read 

trap cleanup EXIT
check_device
zap_usb
#togli_e_metti
if format_usb_$TIPOBOOT ; then 
    termina 
else 
    ERRMSG="ERRORE indeterminato: non dovresti essere qui! "
    help
fi
