#!/bin/bash

# Create GRUB2 bootable images (floppy or hard-disk).
# Copyright (C) 2008 Franklin Piat <fpiat#bigfoot.com>.
# latest version is available from :
#     http://www.klabs.be/~fpiat/linux/boot/grub/mkgrub-diskimg.sh
#
# This file 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., 51 Franklin St - Suite 330, Boston, MA 02110, USA.

# Initialize some variables.
PACKAGE_VERSION=0.01
type=ext2
size=
media=
debug=no
is_mounted=0
sudo=sudo

# Declare some functions
usage () {
	cat <<XXX
Usage: $0 --fd [--size=[1440|2880]] [--type=[fat|ext2]] filename
Usage: $0 --hd [--size=[size]] [--type=[ext2]] filename
Create a floppy or hard disk image, image

  -h, --help      Print this message and exit
  --hd            Build a hard disk image (with partition table)
  --fd            Build a floppy disk)
  --size          Disk size in KiB (default sizes: floppy=>1.44MiB, hd=>10MiB )
  --type          Partition type. currently only fat, or ext2 (default ext2).

XXX
}

die() {
	if [ $is_mounted == 1 ]; then
		$sudo umount /mnt/loop
	fi
	echo $1
	[ -f /tmp/core.img ] && rm /tmp/core.img
	exit;
}


# Check the arguments.
if [ "$1" == "" ] ; then
	usage
	exit
fi

for option in "$@"; do
    case "$option" in
    -h | --help)
	usage
	exit 0 ;;
    -v | --version)
	echo "mkgrubimage ${PACKAGE_VERSION}"
	exit 0 ;;
    --type=ext2 | --type=fat)
	type=`echo "$option" | sed 's/--type=//'` ;;
    --size=*)
    	
	size=`echo "$option" | sed 's/--size=//'` ;;
    --fd |--hd )
	if test "x$media" != x; then
	    echo "Media type already specified (was --$media)" 1>&2
	    exit 1
	fi
	media=`echo "$option" | sed 's/^--//'` ;;
    # This is an undocumented feature...
    --debug)
	debug=yes ;;
    -*)
	echo "Unrecognized option \`$option'" 1>&2
	exit 1
	;;
    *)
	if test "x$file" != x; then
	    echo "Error Can't specify more than one image" 1>&2
	    exit 1
	fi
	file="${option}" ;;
    esac
done

if test "x$media" = x; then
	echo "Media not specified (--fd or --hd)"
	exit 1
fi

if test "x$size" = x; then
	case $media in
	hd )
		size=10240
		;;
	fd )
		size=1440
		;;
	esac
fi


if test "x$file" = x; then
	echo "Image filename not speficied"
	exit 1
fi

# filesystem to mount's type mapping.
if [ "$type" == "fat" ] ; then
	mount_type=vfat
else
	mount_type=$type
fi


# If the debugging feature is enabled, print commands.
if test $debug = yes; then
	echo FILE:$file
	echo PARTITION-TYPE:$type
	echo SIZE:$size
	echo MEDIA:$media
	set -x
fi

if [ -f "$file" ]; then 
	die "ERROR: file '$file' already exists"
fi

if [ "$UID" -eq "0" ]; then
	sudo=
fi


if [ "$media" == "hd" ]; then
	DISKSIZE=$(( $size *1024 ))
	offset=$((32*512))
	dd if=/dev/zero of=$file bs=1024 count=$size
	parted $file mklabel msdos mkpart primary 0 $(( ($DISKSIZE - $offset) /1024 /1024))  mkfs 1 $mount_type toggle 1 boot || die "ERROR: parted failed"
	fdisk -l $file
	#mount -o loop,offset=$((32*512)) $file /tmp/loop
	ROOT=hd0
	PART=hd0,1
	TYPE=hd
else
	dd if=/dev/zero of=$file bs=1024 count=$size
	#cp /tmp/blank_floppy.ima $file
	#bximage -fd -size=1.44 -q $file
	ROOT=fd0
	PART=fd0
	TYPE=fd
fi

grub-mkimage  -v -o /tmp/core.img _chain blocklist ls pc biosdisk $type fshelp  cat help terminal boot  || die "ERROR: grub-mkimage failed"

$sudo mkdir -p /mnt/loop

if [ "$media" == "hd" ]; then
	#done by parted above : /sbin/mke2fs $file
	$sudo mount -o loop,offset=$offset -t $mount_type $file /mnt/loop || die "ERROR: mount failed"
else
	#it's possible to reserve more space on FAT disks... not sure it's helpful.
	#CoreImg=$(( $(cat /tmp/core.img | wc -c) /512 +1 ))
	#echo "Reserving $CoreImg sectors"
	#mkfsdos -R $Coreimg ... needs testing

	/sbin/mkfs.$mount_type $file || die "ERROR: mkdosfs failed"
	$sudo mount -o loop -t $mount_type $file /mnt/loop || die "ERROR: mount failed"
fi
is_mounted=1

$sudo mkdir -p /mnt/loop/boot/grub
$sudo cp /usr/lib/grub/i386-pc/boot.img /tmp/core.img /usr/lib/grub/i386-pc/*.mod /mnt/loop/boot/grub || die "ERROR: can't copy files"
font=unicode
[ "$media" == "fd" -a "$size" == "1440" ] && font=ascii
cp /usr/share/grub/{ascii,$font}.pff /mnt/loop/boot/grub/
[ "$media" == "hd" ] && cp /usr/share/images/desktop-base/debian-blueish-wallpaper-640x480.tga /mnt/loop/boot/grub/bg.tga
#TODO:	copy tga image

#copy ing grub.cfg from current folder, otherwise build a sample one.
echo "($ROOT)	$file" > /tmp/tmp_device.map
$sudo grub-setup -d /mnt/loop/boot/grub -v -r "($PART)" -m /tmp/tmp_device.map "($ROOT)" || die "ERROR: grub-setup failed"

[ -f /mnt/loop/boot/grub/grub.cfg ] && chmod 664 /mnt/loop/boot/grub/grub.cfg
test -f grub.cfg && $sudo cp -f grub.cfg /mnt/loop/boot/grub/
test -f grub.cfg || $sudo cat >/mnt/loop/boot/grub/grub.cfg <<TAC
set default=0
set timeout=30
set root=($PART)

insmod font
font ($PART)/boot/grub/$font.pff
insmod vbe
insmod gfxterm
set menu_color_normal=white/black
set menu_color_highlight=red/black
set gfxmode=640x480
insmod terminal
terminal gfxterm

insmod tga
background_image ($PART)/boot/grub/bg.tga

menuentry "Debian GNU/Linux (sample)" {
        linux   (hd0,1)/boot/vmlinuz-2.6.23-1-686 root=/dev/sda1 ro 
	initrd  (hd0,1)/boot/initrd.img-2.6.23-1-686
}
menuentry "Test" {
	configfile /boot/grub.cfg
}
TAC

die "Done"
