#!/bin/sh

#
# Copyright 2009 Daniel O'Connor <darius@dons.net.au>
#
# Distributable under the 2 clause BSDL
#

#
# Inspired/cribbed by Luigi Rizzo's iso2flash script
# from http://info.iet.unipi.it/~luigi/FreeBSD/
#

# Device to write to
DEV=/dev/da0
# Base directory to copy install image from
SRC=/

if [ $# -ge 1 ]; then
    DEV=$1
fi

if [ $# -ge 2 ]; then
    SRC=$2
fi

traphandler () {
    echo "aborted, cleaning up"

    if [ ! -z "$tmpdir" ]; then
	rm -rf "$tmpdir"
    fi

    exit 1
}

if [ `id -u` != 0 ]; then
    echo "This must be run as root, exiting"
    exit 1
fi

if [ ! -c $DEV ]; then
    echo "$DEV is not a character device, aborting"
    exit 1
fi

if [ ! -e $SRC/boot -o ! -d $SRC/boot ]; then
    echo "$SRC does not have a boot directory"
    exit 1
fi

echo "*** WARNING WARNING WARNING WARNING WARNING WARNING ***"
echo "    This process will destroy all data on $DEV"
echo "*** WARNING WARNING WARNING WARNING WARNING WARNING ***"
read -p "Please enter 'yes' to continue: " answer
if [ "$answer" != "yes" ]; then
    echo "aborting..."
    exit 1
fi

trap traphandler 1 2 15

tmpdir=`mktemp -d /tmp/makeusb.XXXXX`
if [ $? -ne 0 ]; then
    echo "Can't create temporary directory, exiting"
    exit 1
fi

# Copy the stuff we need to boot into a staging area
# We need the loader, kernel, and perhaps an MFS (eg with sysinstall)
mkdir $tmpdir/img
cp -r $SRC/boot $tmpdir/img

# Build FS image
makefs -t ffs -o bsize=4096 -o fsize=512 -f 50 $tmpdir/boot.img $tmpdir/img
if [ $? -ne 0 ]; then
    echo "Can't run makefs"
    exit 1
fi

# Label the image
bsdlabel -Bw -f $tmpdir/boot.img auto
if [ $? -ne 0 ]; then
    echo "Can't run bsdlabel"
    exit 1
fi

# Munge slice table
bsdlabel -f $tmpdir/boot.img | sed -e '/  c:/{p;s/c:/a:/;}' | bsdlabel -R -f $tmpdir/boot.img /dev/stdin

gzip $tmpdir/boot.img

# init MBR, fdisk does all the number crunching
fdisk -qBI $DEV
if [ $? -ne 0 ]; then
    echo "Failed to init $DEV's MBR with fdisk"
    exit 1
fi

# Mangle the MBR fdisk made and make it a DOS partition
fdisk -qp $DEV | sed -e 's/0xa5/0x0c/g' | fdisk -qf - $DEV

if [ $? -ne 0 ]; then
    echo "Failed to fdisk $DEV with DOS MBR"
    exit 1
fi

# newfs the newly created partition
newfs_msdos ${DEV}s1
if [ $? -ne 0 ]; then
    echo "Unable to newfs ${DEV}s1"
    exit 1
fi

# Mount it so we can copy the image over
mkdir $tmpdir/mnt
mount -t msdosfs ${DEV}s1 $tmpdir/mnt
if [ $? -ne 0 ]; then
    echo "Unable to mount ${DEV}s1 on $tmpdir/mnt"
    exit 1
fi

# Copy image onto disk
cp $tmpdir/boot.img.gz $tmpdir/mnt/

# Create syslinux config file
# We use memdisk to load the boot image, the loader will read this and
# load the kernel and perhaps an MFS and then boot.
cat >$tmpdir/mnt/syslinux.cfg <<EOF
display splash.txt
default FreeBSD
label FreeBSD
  kernel memdisk
  append raw ro initrd=boot.img.gz
EOF
printf %blogo.lss\\n \\030 >$tmpdir/mnt/splash.txt

# Copy memdisk for syslinux to use
cp /usr/local/share/syslinux/memdisk $tmpdir/mnt

# Unmount so syslinux can frob the boot sector
umount $tmpdir/mnt
rm -f $tmpdir/boot.img.gz

# Install syslinux
# XXX: need the -f because the port is missing a patch
syslinux -f ${DEV}s1

# XXX: why doesn't the initial fdisk -B obviate the need for this?
boot0cfg -B -s1 ${DEV}

# cleanup
rm -rf "$tmpdir"
