#!/bin/bash
#
# mkrescue
#
#	30-Oct-2001	original version 1.0
#
# Revision history:
#	09-Apr-2002	John Coffman	modify for lilo 22.3   1.1
#	09-Jun-2002	John Coffman	get keyboard translation table 1.2
#					(suggested by Qing Liu)
#	07-May-2003	John Coffman	add nowarn for lilo 22.5.2  1.3
#	13-May-2003	John Coffman	use default image, add append=  1.4
#	24-May-2003	John Coffman	specify ext2 params for xtra space
#	26-May-2003	John Coffman	el-torito-bootable-CD   2.1
#	30-May-2003	   "		add lilo version check  2.1
#	07-Jul-2003	   "		determine loopback dynamically 2.3
#

debug=false
# set the version number on this command
version=2.3
# set the version of LILO required to run
major=22
minor=5
revision=5


usage () {
    cat <<EOF

usage:	`basename $0` [--help]
	`basename $0` [--version]
	`basename $0` [--device <device>] [--fast] [--fs ext2|msdos|minix]
		[--initrd <file> --kernel <file>] [--keymap <keymap.ktl>] 
		[--append <string>] [--nocompact] [--noformat] [--root <device>]
		[--size 1440|1200|2880]

  --device  is the floppy drive; e.g.,  /dev/fd0
  --fast  specifies creation using a loopback device, which may be faster
  --fs  is the filesystem to make on the device; e.g.,  ext2
  --help  prints this helpfile
  --iso  create a bootable ISO image to burn to a CD-R or CD-RW
  --keymap  is the keyboard translation table; default to same as lilo.conf
  --noformat  bypasses creation of a new filesystem on device
  --nocompact  omits lilo map file compaction
  --size  is assumed to be 1440 (1.44M), unless 1200 or 2880 is specified
  --initrd and --kernel  are the initial ramdisk & kernel files
  --append  is a string used to specify kernel options
  --root  is the root filesystem for the boot floppy; e.g., current
  --version  prints the version number of `basename $0`

Used without any arguments, `basename $0` will use the default kernel in
/etc/lilo.conf, the companion initrd (if any), and the specified root
filesystem to make a bootable rescue floppy.

EOF
#
# --install & --debug are undocumented above
#
#
    exit $1
}



lilo=/sbin/lilo
#lilo=$(pwd)/lilo
config=/etc/lilo.conf
#config=$(pwd)/lilo.conf

compact=-c
device=/dev/fd0
fs=ext2
mount=/tmp/mkrescue-flp
mfile=/tmp/mkrescue-emu
#loopback=loop4
install=text
isoimage=no
format=yes
root=current
fast=slow
size=0
bootcmd=
append=
initrd=
boot=/boot
diag=no
if [ -b /dev/hda ]; then
	master=/dev/hda
elif [ -b /dev/sda ]; then
	master=/dev/sda
elif [ -b /dev/ide/host0/bus0/target0/lun0/disc ]; then
	master=/dev/ide/host0/bus0/target0/lun0/disc
elif [ -b /dev/scsi/host0/bus0/target0/lun0/disc ]; then
	master=/dev/scsi/host0/bus0/target0/lun0/disc
else
	master=
fi


VERSION=$($lilo -V | sed "/version/s/.*n //" | sed "/,/s/,.*//" )

NVERSION=$(echo $VERSION | sed "s/\\./ /g")

DASH=$(echo $VERSION | sed "/-/s/.*-//" )
if [ "$DASH" = "$VERSION" ]; then
	DASH=0
else
	NVERSION=$(echo $NVERSION | sed "s/-.*//")
fi
MAJOR=$(echo $NVERSION | sed "s/ .*//")
MINOR=$(echo $NVERSION | sed -e "s/$MAJOR //" -e "s/ .*//" )
if [ "$MINOR" = "$NVERSION" ]; then
	MINOR=0
fi
REVISION=$(echo $NVERSION | sed "s/$MAJOR $MINOR //")
if [ "$REVISION" = "$NVERSION" ]; then
	REVISION=0
fi
REVISION=$(echo $REVISION | sed "s/ .*//")
if [ "$MINOR" -gt 49 ]; then MINOR=$(expr $MINOR % 10); fi

if [ $debug = true ]; then
echo ""
echo VERSION $VERSION
echo ""
echo MAJOR $MAJOR
echo MINOR $MINOR
echo REVISION $REVISION
echo DASH $DASH
echo ""
fi

if [ "$MAJOR" -lt "$major" \
	-o "$MINOR" -lt "$minor" \
		-o $REVISION -lt "$revision" ]
then
    echo `basename $0` version $version
    echo "LILO version $major.$minor.$revision (or newer) is required."
    exit 0
fi

rm -rf $mount 2>/dev/null

#image=`cat /proc/cmdline | sed "s/.*BOOT_IMAGE=//" | sed "s/ .*//"`
image=`$lilo -C $config -I " " D`

kernel=`$lilo -C $config -I $image i`
if [ "$kernel" = "" ]; then exit 1;
elif [ $debug = "true" ]; then echo kernel = "$kernel";
fi

initrd=`$lilo -C $config -I $image r`
if [ "$initrd" = "" ]; then exit 1;
elif [ $debug = "true" ]; then echo initrd = "$initrd";
fi
if [ "$initrd" = "No initial ramdisk specified" ]; then initrd= ; fi

append=`$lilo -C $config -I $image a`
if [ "$append" = "" ]; then exit 1;
elif [ $debug = "true" ]; then echo append = \"$append\";
fi
if [ "$append" = "No append= was specified" ]; then append= ; fi

keymap=`$lilo -C $config -I $image k`
if [ "$keymap" = "" ]; then exit 1;
elif [ $debug = "true" ]; then echo keymap = "$keymap";
fi

root=`mount | grep " on / type" | sed "s/ .*//"`
if [ -z $root ]; then
	echo "Cannot find mounted root partition"
	echo "Using current root"
	root=current
fi


while [ $# -gt 0 ]; do
    case $1 in
	--append)
	    shift
	    append=$1
	    ;;
	--debug)
	    debug=true
	    ;;
	--device)
	    shift
	    device=$1
	    ;;
	--fast)
	    fast=fast
	    ;;
	--fs)
	    shift
	    fs=$1
	    ;;
	-h)
	    usage 0
	    ;;
	--help)
	    usage 0
	    ;;
	--initrd)
	    shift
	    initrd=$1
	    ;;
	--install)
	    shift
	    install=$1
	    ;;
	--iso)
	    isoimage=yes
	    ;;
	--kernel)
	    shift
	    kernel=$1
	    ;;
	--keymap)
	    shift
	    keymap=$1
	    ;;
	--nocompact)
	    compact=
	    ;;
	--noformat)
	    format=no
	    ;;
	--root)
	    shift
	    root=$1
	    ;;
	--size)
	    shift
	    size=$1
	    ;;
	--version)
	    echo `basename $0` version $version
	    exit 0
	    ;;
	*)
	    echo "unrecognized argument: " $1
	    usage 1
	    ;;
    esac

    shift
done

if [ $isoimage = yes ]; then
    fast=fast
    if [ $size = 0 ]; then
	size=2880
    fi
    if [ $device = "/dev/fd0" ]; then
	device=rescue.iso
    fi
else
	umount $device 2>/dev/null 1>/dev/null
fi

if [ $size = 0 ]; then
    size=1440
fi

if [ $size = 1200 ]; then
    sects=15
elif [ $size = 2880 ]; then
    sects=36
    install=menu
    if [ -f $boot/diag1.img -a -f $boot/diag2.img ]; then
	diag=yes
    fi
elif [ $size = 1440 ]; then
    sects=18
else
    echo "--size must be 1200 or 1440; --size 1440 assumed."
    sects=18
    size=1440
fi

if [ $fs != msdos -a $fs != ext2 -a $fs != minix ]; then
    echo "illegal option:  --fs" $fs
    echo "   must be either  msdos  or  ext2  or  minix"
    exit 1
fi

if [ $fs = msdos ]; then
	mountconfig=$mount/lilo.cnf
else
	mountconfig=$mount/lilo.conf
fi

if [ $debug = "true" ]; then
	umount $mfile
	echo lilo = $lilo
	echo device = $device
	echo image = $image
	echo kernel = $kernel
	echo initrd = $initrd
	echo append = \"$append\"
	echo install = $install
	echo format = $format
	echo fs = $fs
	echo size = $size
	echo root = $root
	echo compact = $compact
	echo keymap = $keymap
	echo isoimage = $isoimage
	echo master = $master
fi

if [ ! -f $kernel ]; then
	echo "Kernel file " $kernel " does not exist"
	exit 1
fi

if [ ! -z $initrd ]; then
	if [ ! -f $initrd ]; then
		echo "Initial ramdisk file " $initrd " does not exist"
		exit 1
	fi
fi

if [ $isoimage != yes ]; then
	echo ""
	echo "Insert a blank floppy into $device"
	echo "All information on this floppy will be destroyed"
	echo "Press [Enter] to proceed, ^C to abort"
	read aline
fi

if [ "$fast" = fast ]; then

	rm -rf $mount $mfile
	mkdir $mount
	dd bs=1024 count=$size of=$mfile if=/dev/zero
	echo Making filesystem
	if [ "$fs" = ext2 ]; then
		echo y | mkfs.$fs -N 24 -b 1024 $mfile $size
	else
		echo y | mkfs.$fs $mfile
	fi
	echo Mounting filesystem
	mount -t $fs -o rw,loop $mfile $mount
	if [ $debug = true ]; then
		mount
	fi
	loopback=`mount | grep $mfile | sed -e "sX.*loop=/dev/XX" -e "s/).*//"`
	disk="/dev/$loopback"
	if [ $debug = true ]; then
		echo "disk=$disk"
	fi

else

	if [ "$format" = "yes" ]; then
		echo Formatting $device with $fs filesystem...
		dd of=$device if=/dev/zero bs=512 count=1
		if [ "$fs" = ext2 ]; then
			mkfs -t $fs -N 24 -b 1024 $device 1>/dev/null 2>/dev/null
		else
			mkfs -t $fs $device 1>/dev/null 2>/dev/null
		fi
		echo done.
		echo ""
	fi

	rm -rf $mount
	mkdir $mount
	mount -t $fs -o rw $device $mount

	rm -rf $mount/*
	disk=$device

fi

cat > $mountconfig <<EOF
#  Begin mkrescue $version configuration file
install=$install
boot=$device
map=map
backup=/dev/null
message=message
prompt
timeout=150
nowarn
geometric
disk=$disk bios=0x00
  sectors=$sects heads=2 cylinders=80
EOF
if [ "$master" != "" -a $isoimage = yes ]; then
	echo "disk=$master" >>$mountconfig
	echo "  bios=0x80" >>$mountconfig
elif [ "$master" != "" -a $debug = true ]; then
	echo "disk=$master" >>$mountconfig
	echo "  bios=0x80 inaccessible" >>$mountconfig
fi

if [ $keymap != us.ktl ]; then 
	echo "keytable=lang.ktl" >>$mountconfig
fi

if [ $isoimage = yes ]; then 
	echo "el-torito-bootable-CD" >>$mountconfig
fi

echo " " >>$mountconfig
echo "image=linux" >>$mountconfig

if [ ! -z $initrd ]; then
	echo "  initrd=initrd" >>$mountconfig
fi

if [ ! -z "$append" ]; then
	echo "  append=\"$append\"" >>$mountconfig
fi

cat >> $mountconfig <<EOF
  root=$root
  read-only
EOF

if [ "$master" != "" -a $size = 2880 ]; then
cat >> $mountconfig <<EOF
other=$master
  unsafe
  label=hard_disk
EOF
fi

if [ "$diag" = yes ]; then
cp -pv $boot/diag1.img $mount
cp -pv $boot/diag2.img $mount
cat >> $mountconfig <<EOF
image=diag1.img
  label=diagnostic_1
image=diag2.img
  label=diagnostic_2
EOF
fi
echo >>$mountconfig "#  End of mkrescue-generated configuration file"

if [ $isoimage = yes ]; then
	comment="El-Torito bootable-CD will boot at end of timeout"
else
	comment="floppy will boot in 15 seconds"
fi

cat > $mount/message <<EOF

MKRESCUE version $version $comment
Use  "boot: linux <options>"  to enter kernel options
The root device is currently configured as  root=$root

EOF
echo `uname --sysname` `uname --release` > $mount/$(uname --release)

sync

if [ $debug = true ]; then
	echo ""
	echo "pause after writing lilo.conf & message ..."
	read aline
fi

echo "Copying files..."
if [ $keymap != us.ktl ]; then 
	cp -pv $keymap $mount/lang.ktl
fi

if [ ! -z $initrd ]; then
	cp -pv $initrd $mount/initrd
fi

cp -pv $kernel $mount/linux
sync

echo "done."
echo ""



log=$(pwd)/mkrescue.log
pushd $mount >/dev/null 2>/dev/null
if [ "$fast" = fast ]; then
	bootcmd="-b /dev/$loopback"
fi

echo Running $lilo ...
if [ $debug = true ]; then
 echo	$lilo -w+ -C $mountconfig $compact $bootcmd -v5 ">$log"
	$lilo -w+ -C $mountconfig $compact $bootcmd -v5 >$log || fast=error
else
	$lilo -C $mountconfig $compact $bootcmd || fast=error
fi
popd >/dev/null 2>/dev/null
if [ "$fast" = error ]; then
	echo lilo failure.
else
	echo done.
fi
echo ""

umount $mount

if [ $fast = error ]; then
	rm -rf $mount
	exit 1
fi

if [ $isoimage = yes ]; then
	echo MKISOFS
	out=$device
	mv $mfile $mount/boot.bin
	mkisofs -J -R -T \
		-V LILO_BOOT -A "Linux Boot CD created by LILO mkrescue" \
		-b boot.bin -c boot.cat -o $out $mount
	cat <<EOF

END MKISOFS:  output is in  '$device'


The bootable CD can be burned with the 'cdrecord' utility
using a command of the form:

	cdrecord [<options>] [dev=<device>] $device

EOF
elif [ "$fast" = fast ]; then
	dd if=$mfile of=$device bs=1024
fi

if [ $debug != true ]; then 
	rm -f $mfile
fi

echo "All done."
echo ""
exit 0
