#!/bin/bash
#
# 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, either version 3 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, see <http://www.gnu.org/licenses/>.

set -e
set -x
set -o pipefail

set_apt_sources() {
    NEW_MIRROR="$1"
    COMPONENTS="main"
    if [ "$ENABLE_NONFREE" = "yes" ]
    then
	    COMPONENTS="main contrib non-free"
    fi

    cat <<EOF > etc/apt/sources.list
deb $NEW_MIRROR $SUITE $COMPONENTS
deb-src $NEW_MIRROR $SUITE $COMPONENTS
EOF

    if [ "$SUITE" != "unstable" ] && [ "$SUITE" != "sid" ]; then
	cat <<EOF >> etc/apt/sources.list

deb http://security.debian.org/ $SUITE/updates $COMPONENTS
deb-src http://security.debian.org/ $SUITE/updates $COMPONENTS

deb $NEW_MIRROR $SUITE-updates $COMPONENTS
deb-src $NEW_MIRROR $SUITE-updates $COMPONENTS
EOF
    fi
}

atheros_wifi() {
    # Fetch and install free software firmware for a couple USB Atheros
    # Wi-Fi devices from Trisqel repository.
    firmware_filename="open-ath9k-htc-firmware_1.3-1_all.deb"
    firmware_hash='5fea58ffefdf0ef15b504db7fbe3bc078c03e0d927bba64085e4b6f2546102f5'

    firmware_url="http://us.archive.trisquel.info/trisquel/pool/main/o/open-ath9k-htc-firmware/$firmware_filename"
    firmware_tempfile="/tmp/$firmware_filename"
    wget "$firmware_url" -O "$rootdir$firmware_tempfile"
    downloaded_firmware_hash=$(sha256sum "$rootdir$firmware_tempfile" | awk -F ' ' '{print $1}')
    if [ "$downloaded_firmware_hash" = "$firmware_hash" ]; then
        chroot "$rootdir" dpkg -i "$firmware_tempfile"
        return
    fi
    echo 'Atheros wifi firmware download verification failed'
    fuser -mvk $rootdir/. || true
    exit 1
}

mount_file_systems() {
    mount /dev     -t devfs  -o bind "$rootdir/dev"
    mount /dev/pts -t devpts -o bind "$rootdir/dev/pts"
    mount /proc    -t proc   -o bind "$rootdir/proc"
    mount /run     -t run    -o bind "$rootdir/run"
    mount /sys     -t sys    -o bind "$rootdir/sys"
}

unmount_file_systems() {
    # XXX: Should be doing strict checks but /dev/pts seems to be
    # prematurely unmounted for some reason perhaps due to issues in
    # parallel builds.  Workaround that.
    umount "$rootdir/dev/pts" || true
    umount "$rootdir/dev" || true
    umount "$rootdir/proc" || true
    umount "$rootdir/run" || true
    umount "$rootdir/sys" || true

    case "$MACHINE" in
        raspberry2 | raspberry3)
            umount "$rootdir/boot/firmware" || true
        ;;
    esac
}

make_source_tarball() {
    # Make source packages available outside of image.
    (
    cd "$rootdir/usr/src/packages"
    tar -czvf "$1" ./*
    )
}

rootdir="$1"
image="$(cd "$(dirname "$2")"; pwd)/$(basename "$2")"

# Create vfat /boot/firmware partition for devices that need it.
case "$MACHINE" in
    raspberry2 | raspberry3)
        umount "$rootdir/boot"
        umount "$rootdir"
        kpartx -dvs "$image"

        parted -s "$image" mkpart primary 0% 60MiB

        # Reorder partitions by start offset
        sfdisk --reorder "$image"

        device=/dev/mapper/$(kpartx -avs "$image" \
            | awk '/^add map / {print $3; exit}')
        mkfs -t vfat "$device"
        parted -s "$image" set 1 lba on

        mount -t btrfs "${device%?}3" "$rootdir"
        mount -t ext2 "${device%?}2" "$rootdir"/boot
        mkdir "$rootdir/boot/firmware"
        mount -t vfat "$device" "$rootdir/boot/firmware"

        fs_uuid=$(blkid -c /dev/null -o value -s UUID "$device")
        echo "UUID=$fs_uuid /boot/firmware vfat errors=remount-ro 0 3" \
             >>"$rootdir"/etc/fstab
        ;;
esac

mount_file_systems
trap unmount_file_systems EXIT

cd "$rootdir"

echo info: building $MACHINE

export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true
export LC_ALL=C LANGUAGE=C LANG=C

# Override libpam-tmpdir setting during build, as the directories
# are not created yet.
export TMP=/tmp/ TMPDIR=/tmp/

# vmdebootstrap sets up systemd-networkd such that it performs DHCP on all
# Ethernet interfaces. This is a problem for Network Manager later taking over.
# Remove the configuration file created by vmdebootstrap so that Network Manager
# that is present in FreedomBox can work without problems. See:
# https://bugzilla.gnome.org/show_bug.cgi?id=793231
rm -f $rootdir/etc/systemd/network/99-dhcp.network

username=fbx
echo "info: creating initial user $username with disabled password!"
chroot $rootdir adduser --gecos $username --disabled-password $username
chroot $rootdir adduser $username sudo

case "$MACHINE" in
    virtualbox)
        # hide irrelevant console keyboard messages.
        echo "echo \"4 4 1 7\" > /proc/sys/kernel/printk" \
            >> /etc/init.d/rc.local
        ;;
esac

set_apt_sources $BUILD_MIRROR
chroot $rootdir apt-get update

# Set a flag to indicate that this is a FreedomBox image
# and FreedomBox is not installed using a Debian package
mkdir -p $rootdir/var/lib/freedombox
touch $rootdir/var/lib/freedombox/is-freedombox-disk-image

cat > $rootdir/usr/sbin/policy-rc.d <<EOF
#!/bin/sh
exit 101
EOF
chmod a+rx $rootdir/usr/sbin/policy-rc.d

if [ -n "$CUSTOM_PLINTH" ]; then
    cp "$CUSTOM_PLINTH" "$rootdir"/tmp
    chroot "$rootdir" apt-get install -y gdebi-core
    chroot "$rootdir" gdebi -n /tmp/"$(basename $CUSTOM_PLINTH)"
fi

if [ -n "$CUSTOM_SETUP" ]; then
    cp "$CUSTOM_SETUP" "$rootdir"/tmp
    chroot "$rootdir" apt-get install -y gdebi-core
    chroot "$rootdir" gdebi -n /tmp/"$(basename $CUSTOM_SETUP)"
else
    chroot "$rootdir" apt-get install -y freedombox-setup
fi

atheros_wifi

script_dir=$(cd "$(dirname "$0")" && pwd)
cp "$script_dir"/hardware-setup $rootdir/tmp
chroot $rootdir /tmp/hardware-setup 2>&1 | \
    tee $rootdir/var/log/hardware-setup.log

rm $rootdir/usr/sbin/policy-rc.d

# freedombox-setup up to version 0.10 had setup steps.
# Setup is delegated to Plinth in later versions.
if [ -f $rootdir/usr/lib/freedombox/setup ]; then
    chroot $rootdir /usr/lib/freedombox/setup 2>&1 | \
        tee $rootdir/var/log/freedombox-setup.log
fi

if [ 'true' = "$SOURCE" ] ; then
    make_source_tarball "${image%.img.temp}"-source.tar.gz

    if [ 'false' = "$SOURCE_IN_IMAGE" ] ; then
	# Remove source packages from image.
	rm -rf "$rootdir/usr/src/packages"
    fi
fi

# Remove SSH keys from the image, freedomxbox-setup does not do that
# anymore.
rm $rootdir/etc/ssh/ssh_host_* || true

# Move hostname to 127.0.1.1 line of /etc/hosts.
# TODO: Can this be changed in vmdebootstrap?
sed -i "s/127.0.0.1.*/127.0.0.1	localhost/" "$rootdir"/etc/hosts
if ! grep -q 127.0.1.1 "$rootdir"/etc/hosts ; then
    sed -i "/127.0.0.1.*/a \
127.0.1.1	freedombox" "$rootdir"/etc/hosts
fi

# copy u-boot to beginning of image
case "$MACHINE" in
    beaglebone)
        dd if=$rootdir/usr/lib/u-boot/am335x_boneblack/MLO of="$image" \
           count=1 seek=1 conv=notrunc bs=128k
        dd if=$rootdir/usr/lib/u-boot/am335x_boneblack/u-boot.img of="$image" \
           count=2 seek=1 conv=notrunc bs=384k
        ;;
    cubietruck)
        dd if=$rootdir/usr/lib/u-boot/Cubietruck/u-boot-sunxi-with-spl.bin of="$image" \
           seek=8 conv=notrunc bs=1k
        ;;
    a20-olinuxino-lime)
        dd if=$rootdir/usr/lib/u-boot/A20-OLinuXino-Lime/u-boot-sunxi-with-spl.bin \
           of="$image" seek=8 conv=notrunc bs=1k
        ;;
    a20-olinuxino-lime2)
        dd if=$rootdir/usr/lib/u-boot/A20-OLinuXino-Lime2/u-boot-sunxi-with-spl.bin \
           of="$image" seek=8 conv=notrunc bs=1k
        ;;
    a20-olinuxino-micro)
        dd if=$rootdir/usr/lib/u-boot/A20-OLinuXino_MICRO/u-boot-sunxi-with-spl.bin \
           of="$image" seek=8 conv=notrunc bs=1k
        ;;
    banana-pro)
        dd if=$rootdir/usr/lib/u-boot/Bananapro/u-boot-sunxi-with-spl.bin \
           of="$image" seek=8 conv=notrunc bs=1k
        ;;
    cubieboard2)
        dd if=$rootdir/usr/lib/u-boot/Cubieboard2/u-boot-sunxi-with-spl.bin of="$image" \
           seek=8 conv=notrunc bs=1k
        ;;
    pcduino3)
        dd if=$rootdir/usr/lib/u-boot/Linksprite_pcDuino3/u-boot-sunxi-with-spl.bin of="$image" \
           seek=8 conv=notrunc bs=1k
        ;;
esac

set_apt_sources $MIRROR
chroot $rootdir apt-get update

cd /
echo "info: killing leftover processes in chroot"
# 2014-11-04 this killed /usr/lib/erlang/erts-6.2/bin/epmd, see
# <URL: https://www.ejabberd.im/epmd?q=epmd > to learn more.
fuser -mvk $rootdir/. || true
