#!/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

# Raspberry Pi blob repo
rpi_blob_repo='https://github.com/Hexxeh/rpi-update'
rpi_blob_commit='31615deb9406ffc3ab823e76d12dedf373c8e087'

# Expected sha256 hash for rpi-update
rpi_blob_hash='9868671978541ae6efa692d087028ee5cc5019c340296fdd17793160b6cf403f'

enable_serial_console() {
    # By default, spawn a console on the serial port
    device="$1"
    echo "Adding a getty on the serial port"
    echo "T0:12345:respawn:/sbin/getty -L $device 115200 vt100" >> /etc/inittab
}

dreamplug_flash() {
    # allow flash-kernel to work without valid /proc contents
    # ** this doesn't *really* work, since there are too many checks
    #    that fail in an emulated environment!  We'll have to do it by
    #    hand below anyway...
    export FK_MACHINE="Globalscale Technologies Dreamplug"
    apt-get install -y flash-kernel
}

dreamplug_repack_kernel() {
# process installed kernel to create uImage, uInitrd, dtb
# using flash-kernel would be a good approach, except it fails in the
# cross build environment due to too many environment checks...
#FK_MACHINE="Globalscale Technologies Dreamplug" flash-kernel
#  so, let's do it manually...

# flash-kernel's hook-functions provided to mkinitramfs have the
# unfortunate side-effect of creating /conf/param.conf in the initrd
# when run from our emulated chroot environment, which means our root=
# on the kernel command line is completely ignored!  repack the initrd
# to remove this evil...

    echo "info: repacking dreamplug kernel and initrd"

    kernelVersion=$(ls /usr/lib/*/kirkwood-dreamplug.dtb | head -1 | cut -d/ -f4)
    version=$(echo $kernelVersion | sed 's/linux-image-\(.*\)/\1/')
    initRd=initrd.img-$version
    vmlinuz=vmlinuz-$version

    mkdir /tmp/initrd-repack

    (cd /tmp/initrd-repack ; \
        zcat /boot/$initRd | cpio -i ; \
        rm -f conf/param.conf ; \
        find . | cpio --quiet -o -H newc | \
        gzip -9 > /boot/$initRd )

    rm -rf /tmp/initrd-repack

    (cd /boot ; \
        cp /usr/lib/$kernelVersion/kirkwood-dreamplug.dtb dtb ; \
        cat $vmlinuz dtb >> temp-kernel ; \
        mkimage -A arm -O linux -T kernel -n "Debian kernel ${version}" \
        -C none -a 0x8000 -e 0x8000 -d temp-kernel uImage ; \
        rm -f temp-kernel ; \
        mkimage -A arm -O linux -T ramdisk -C gzip -a 0x0 -e 0x0 \
        -n "Debian ramdisk ${version}" \
        -d $initRd uInitrd )
}

# Install binary blob and kernel needed to boot on the Raspberry Pi.
raspberry_setup_boot() {
    # Packages used by rpi-update to make Raspberry Pi bootable
    apt-get install -y git-core binutils ca-certificates wget kmod

    rpi_tempdir=/tmp/fbx-rpi-update
    if [ -d $rpi_tempdir ]; then
        rm -rf $rpi_tempdir
    fi
    git clone $rpi_blob_repo $rpi_tempdir
    cd $rpi_tempdir
    git checkout $rpi_blob_commit -b $rpi_blob_commit

    downloaded_rpi_blob_hash=$(sha256sum $rpi_tempdir/rpi-update | awk -F ' ' '{print $1}')
    if [ "$downloaded_rpi_blob_hash" != "$rpi_blob_hash" ]; then
        echo 'WARNING: Unable to verify Raspberry Pi boot blob'
        return
    fi

    cp $rpi_tempdir/rpi-update /usr/bin/rpi-update

    chmod a+x /usr/bin/rpi-update
    mkdir -p /lib/modules
    touch /boot/start.elf
    SKIP_BACKUP=1 SKIP_WARNING=1 rpi-update | tee /root/rpi-update.log
}

# Install binary blob and u-boot needed to boot on the Raspberry Pi 2.
raspberry2or3_setup_boot() {
    pi_version="$1"

    # install boot firmware
    apt-get install --no-install-recommends -y dpkg-dev
    cd /tmp
    apt-get source raspi3-firmware
    cp raspi3-firmware*/boot/* /boot/firmware
    rm -rf raspi3-firmware*
    cd /

    # remove unneeded firmware files
    rm -f /boot/firmware/fixup_*
    rm -f /boot/firmware/start_*

    # u-boot setup
    apt-get install -y u-boot-rpi
    case "$pi_version" in
        raspberry2)
            cp /usr/lib/u-boot/rpi_2/u-boot.bin /boot/firmware/kernel.img
            ;;
        raspberry3)
            cp /usr/lib/u-boot/rpi_3_32b/u-boot.bin /boot/firmware/kernel.img
            ;;
    esac
}


setup_flash_kernel() {
    if [ ! -d /etc/flash-kernel ] ; then
       mkdir /etc/flash-kernel
    fi
    full_machine_name="$1"
    echo -n "$full_machine_name" > /etc/flash-kernel/machine

    # Raspberry Pi 3 Model B can also work with armmp kernel, so add it to the
    # flash-kernel database in addition to the existing arm64. XXX: Remove this
    # override when flash-kernel is updated.
    case "$full_machine_name" in
        "Raspberry Pi 3 Model B")
            mkdir -p /usr/share/flash-kernel/db/
            cat >/usr/share/flash-kernel/db/01-raspberrypi3-freedombox.db <<EOF
Machine: Raspberry Pi 3 Model B
Kernel-Flavors: arm64 armmp armmp-lpae
EOF
            ;;
    esac

    command_line=""
    if [ -n "$2" ] ; then
        command_line="console=$2"
    fi

    if [ -n "$command_line" ] ; then
        echo flash-kernel flash-kernel/linux_cmdline string "$command_line" | debconf-set-selections
    fi

    apt-get install -y flash-kernel
}

stable_mac_address_workaround() {
    # Apply the fix only for stable kernel. Latest kernel in testing and
    # unstable already sets up a stable MAC address based on CPU id of the Pi.
    if [ "$SUITE" != "stable" -a "$SUITE" != "stretch" ]; then
        return
    fi

    # XXX: With Debian Stretch on Raspberry Pi 2, the kernel is not
    # reading the hardware MAC address, so it uses a random one. This
    # causes the IP address to change on every boot.

    # As a workaround, have NetworkManager provide a stable MAC for
    # the ethernet device. It is generated by hashing the device name
    # and a private key, so it is unique for each box.
    cat >/etc/NetworkManager/conf.d/30-stable-mac.conf <<EOF
[connection-mac-randomization]
ethernet.cloned-mac-address=stable
EOF
}

case "$MACHINE" in
    dreamplug|guruplug)
        dreamplug_flash
        dreamplug_repack_kernel
        enable_serial_console ttyS0
        ;;
    raspberry)
        raspberry_setup_boot
        ;;
    raspberry2)
        raspberry2or3_setup_boot 'raspberry2'
        setup_flash_kernel 'Raspberry Pi 2 Model B'
        flash-kernel
        stable_mac_address_workaround
        ;;
    raspberry3)
        raspberry2or3_setup_boot 'raspberry3'
        setup_flash_kernel 'Raspberry Pi 3 Model B'
        flash-kernel
        stable_mac_address_workaround
        ;;
    beaglebone)
        setup_flash_kernel 'TI AM335x BeagleBone Black' 'ttyO0'
        ;;
    cubietruck)
        setup_flash_kernel 'Cubietech Cubietruck'
        ;;
    a20-olinuxino-lime)
        setup_flash_kernel 'Olimex A20-OLinuXino-LIME'
        ;;
    a20-olinuxino-lime2)
        setup_flash_kernel 'Olimex A20-OLinuXino-LIME2'
        ;;
    a20-olinuxino-micro)
        setup_flash_kernel 'Olimex A20-Olinuxino Micro'
        ;;
    banana-pro)
        setup_flash_kernel 'LeMaker Banana Pro'
        ;;
    cubieboard2)
        setup_flash_kernel 'Cubietech Cubieboard2'
        ;;
    pcduino3)
        setup_flash_kernel 'LinkSprite pcDuino3'
        ;;
esac
