#!/bin/sh
# vi: ts=4 noexpandtab
#
#    Copyright (C) 2010 Canonical Ltd.
#
#    Authors: Scott Moser <smoser@canonical.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, version 3 of the License.
#
#    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, see <http://www.gnu.org/licenses/>.

TEMP_D=""

error() { echo "$@" 1>&2; }
fail() { [ $# -eq 0 ] || error "$@"; exit 1; }
Usage() {
	cat <<EOF
Usage: ${0##*/} loader.img output.img
   Create a multiboot floppy image that will multiboot 'loader.img'
   where loader.img is a multiboot complient loader

   The output.img file can then be booted with
      kvm -fda output.img -boot a -drive ...
   and will load 'loader.img'
EOF
}
bad_Usage() { Usage 1>&2; fail "$@"; }
cleanup() {
	[ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}"
}

getsize() {
	local f="$1" size=""
	size=$(ls -l "${f}" 2>/dev/null | awk '{print $5}') &&
		[ -n "${size}" ] && _RET=${size} && return 0
}
checksize() {
	getsize "$1" || return 1
	[ "${_RET}" "$2" "$3" ]
}

mk_grub_rescue() {
	local input=${1} output=${2}
	local bdir="${TEMP_D}/bdir"
	local err="${TEMP_D}/err"
	local modules="configfile"
	local modules=""
	mkdir "${bdir}" &&
		mkdir -p "${bdir}/boot/grub" &&
		cp "${input}" "${bdir}/boot/grub/loader.img" &&
		cat > "${bdir}/boot/grub/grub.cfg" <<EOF
multiboot /boot/grub/loader.img
boot
EOF
		[ $? -eq 0 ] || return
		grub-mkrescue --output="${output}" \
			${modules:+"--modules=${modules}"} "${bdir}" > "${err}" 2>&1 ||
			{ cat "${err}" 1>&2; return 1; }
}

short_opts="h"
long_opts="help"
getopt_out=$(getopt --name "${0##*/}" \
	--options "${short_opts}" --long "${long_opts}" -- "$@") &&
	eval set -- "${getopt_out}" ||
	bad_Usage

mode="grub-rescue-floppy"
while [ $# -ne 0 ]; do
	cur=${1}; next=${2};
	case "$cur" in
		-h|--help) Usage; exit 0;;
		--) shift; break;;
	esac
	shift;
done

[ $# -eq 2 ] || bad_Usage "must multiboot loader input and output file"

TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/.${0##*/}.XXXXXX") ||
	fail "failed to make tempd"
trap cleanup EXIT

loader=${1}
output=${2}

case "${mode}" in
	grub-rescue-floppy)
		mk_grub_rescue "${loader}" "${output}" ||
			fail "failed to make rescue floppy"
		checksize "${output}" -lt $((2880*1024)) ||
			fail "output of mk_rescue was to large for floppy"
		size=${_RET}
		truncate --size 2880K "${output}" ||
			fail "failed to pad ${output} to 2880K"
		echo "created ${mode} loader in ${output} (payload $size)"
		;;
	grub-rescue-cdrom)
		mk_grub_rescue "${loader}" "${output}" ||
			fail "failed to make rescue cdrom"
		echo "created ${mode} loader in ${output}"
		;;
esac

[ $? -eq 0 ] || fail "failed to create loader"
