#!/bin/sh
# $Id: autoinst.sh,v 1.22 2014/12/02 20:21:17 asau Stab $
set -e

_progname="${0##*/}"
usage="usage: ${0##*/} [-s swap-size-mb] [-S swap-size-blocks] device-name"

SWAPSIZE=
while getopts "s:S:" opt; do
   case $opt in
       s) SWAPSIZE=$((2 "*" 1024 "*" ${OPTARG}));; # swap size in MiB
       S) SWAPSIZE=$((0 + ${OPTARG}));;
       \?) echo "$usage" 1>&2; exit 1;;
   esac
done
shift $(expr $OPTIND - 1)

if [ $# != 1 ]; then echo "$usage" 1>&2; exit 1; fi

SD="$1"

# Apply defaults:
: ${SD:?device name is empty}
: ${SWAPSIZE:=$((2 "*" 1024 "*" 16))} # default to 16 MiB

# Path to installation sets:
: ${OBJDIR:=/usr/obj}
: ${RELEASEDIR:=${OBJDIR}/releasedir}
: ${SETSDIR:=${RELEASEDIR}/$(uname -m)/binary/sets}

: ${TMPDIR:=/tmp} # temporary directory

# Disk partitioning
gpt create -f ${SD}

# Unallocated space limits:
LIMITS="$(gpt show ${SD} | awk 'NF==2 {print $1, $2;}')" # unallocated space
START="${LIMITS%% *}" # first number
SIZE="${LIMITS##* }" # second number

# Align:
ALIGN=64 # assume it is always greater than START (usually 34)
SIZE=$((${SIZE} - (${ALIGN} - ${START})))
START=${ALIGN}

# Root partition limits:
ROOTSTART=${START}
ROOTSIZE=$((${SIZE} - ${SWAPSIZE}))
ROOTSIZE=$((${ROOTSIZE} / ${ALIGN} * ${ALIGN})) # align

SWAPSTART=$((${ROOTSTART} + ${ROOTSIZE})) # aligned due to ROOTSTART and ROOTSIZE both aligned
# SWAPSIZE is defined already

# Generate partition labels:
ROOT_LABEL="root-$(openssl rand 6 -base64 2>/dev/null)"
SWAP_LABEL="swap-$(openssl rand 6 -base64 2>/dev/null)"

# Create partitions:
gpt add -i 1 -t  ffs -l "${ROOT_LABEL}" -b ${ROOTSTART} -s ${ROOTSIZE} ${SD}
gpt add -i 2 -t swap -l "${SWAP_LABEL}" -b ${SWAPSTART} -s ${SWAPSIZE} ${SD}
ROOT="$(dkctl ${SD} addwedge root ${ROOTSTART} ${ROOTSIZE} ffs | awk '{print $1}')"
SWAP="$(dkctl ${SD} addwedge swap ${SWAPSTART} ${SWAPSIZE} swap | awk '{print $1}')"

# Make it bootable
gpt biosboot -i 1 ${SD}

mnt=${TMPDIR}/${_progname}.$$

# Now create file systems, and unpack sets
newfs -O2 ${ROOT}
mkdir ${mnt}
mount /dev/${ROOT} ${mnt}

cd ${mnt}
for s in base etc; do pax -zrpe -f ${SETSDIR}/$s.tgz; done
for s in kern-GENERIC modules; do pax -zrpe -f ${SETSDIR}/$s.tgz; done

# Make it bootable:
cp usr/mdec/boot .
installboot -vf -o timeout=2 /dev/r${ROOT} /usr/mdec/bootxx_ffsv2
# ...only make sure that this boot code corresponds to file system in newfs above.

# Populate /dev
(cd dev && sh MAKEDEV all)

# Additional mount points:
mkdir proc kern

# Generate fstab
cat > etc/fstab <<EOF
NAME=${ROOT_LABEL} / ffs rw,log 1 1
NAME=${SWAP_LABEL} none swap sw 0 0
ptyfs /dev/pts ptyfs rw
kernfs /kern kernfs rw
procfs /proc procfs rw
tmpfs /tmp tmpfs rw
EOF

# Generate rc.conf
cat > etc/rc.conf <<EOF
if [ -r /etc/defaults/rc.conf ]; then
       . /etc/defaults/rc.conf
fi
rc_configured=yes
EOF

# Wrap up:
sync
cd # don't hold file system
umount ${mnt}
rmdir ${mnt}