#!/bin/bash
#
#  WARNING -   WARNING -  WARNING -  WARNING -   WARNING -  WARNING - WARNING #
#  WARNING -   WARNING -  WARNING -  WARNING -   WARNING -  WARNING - WARNING #
#                     This script will DESTROY your installation.
#                     This script will DESTROY your installation.
#                     This script will DESTROY your installation.
#                     This script will DESTROY your installation.
#                     This script will DESTROY your installation.
#  WARNING -   WARNING -  WARNING -  WARNING -   WARNING -  WARNING - WARNING #
#  WARNING -   WARNING -  WARNING -  WARNING -   WARNING -  WARNING - WARNING #
#
################################################################################
# Script : sa64-ins-write
# Purpose: Write the Slackware A-i-O Installer to the MMC storage device that
#          presently holds OS's /boot partition (file system label 'SLKboot').
#          This supports all officially supported Hardware Models.
#          This is to prepare the Slackware ARM build hosts to either test the
#          Slackware Installer, or to reinstall a build host.
# Author :  Stuart Winter <mozes@slackware.com>
# Version: 1.00, 13-Jan 2023
################################################################################
#
# Copyright 2023 Stuart Winter, Earth, Milky Way, ""
# All rights reserved.
#
# Redistribution and use of this script, with or without modification, is
# permitted provided that the following conditions are met:
#
# 1. Redistributions of this script must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#
#  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
#  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
#  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
#  EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
#  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
#  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
#  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
#  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
#  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
################################################################################
#
# Usage:
# On an existing installation of Slackware, as root run this tool within the
# directory that contains the Slackware A-i-O Installer images that are
# availale here:
# http://ftp.arm.slackware.com/slackwarearm/platform/aarch64/bootware/installer-aio/
#
# Example:
#    $ cd installer-aio
#    $ ./tools/sa64-aio-write
#
# What this script does:
#
# 1. Picks the appropriate A-i-O Installer for the Hardware Model on which
# you run the script.
# By default it'll pick 'slackwareaarch64-current', but you can supply it with
# an alternate, perhaps a stable release:
#    $ ./tools/sa64-aio-write -a slackwareaarch64-15.1
#
# 2. Write to the SD card that presently contains the active Slackware
# OS /boot partition, labeled 'SLKboot'.
#
# 3.  umount the /boot file systems (including any Hardware Model Native
# Boot Loader partitions, as found on the RPi and HoneyComb), then dump the
#
# 4.  Dump the A-i-O image to the SD card.
#
# 5 . Reboot.
################################################################################
# To do:
# Handle 'bare' Installer images. Auto discovery of the type:
# It should be a case of dropping through some checking for file names, since
# the aio installers have a specific name.
################################################################################

[ $( id -u ) != 0 ] && { echo "Error: You must be root" ; exit 1 ;}

# Determine the SD card in play.
# Assumes there's only 1 - which on all known Hardware Models, is the case.
# This does not include SD cards in USB dongles, only on-board MMC slots.
# Note: eMMC is excluded.
function find_sdcard() {
  local mmc
  while read mmc; do
     grep -q "SD" /sys/block/${mmc#/dev/}/device/type && { echo ${mmc} ; break ;}
  done< <( ls /dev/mmcblk{0..9} 2>/dev/null )
}

# Determine the architecture:
case "$( uname -m )" in
   arm*)    slkarch=arm;;
   *)       slkarch="$( uname -m )" ;;
esac

# We'll default to Slackware -current:
slackver=current
AIODIR="slackware${slkarch}-${slackver}" # e.g. slackwareaarch64-current

# Parse any command line operators:
PARAMS="$( getopt -qn "$( basename $0 )" -o a: -l aio-dir: -- "$@" )"
eval set -- "${PARAMS}"
for param in $*; do
  case "$param" in
     -a|--aio-dir) AIODIR="$2"
                   shift 2;;
     --) shift; break;;
  esac
done

# Sanity check that we found a platform dir:
[ ! -d $AIODIR ] && {
   echo "ERROR: cannot find A-i-O Installer directory $AIODIR"
   exit 1 ;}

# Determine which Hardware Model we're running on:
HWM=$( slk-hwm-discover )
case "$HWM" in
   "Pine64 RockPro64"*|"Pine64 Pinebook Pro"*)
      IMG=uboot_generic.img ;;

   "SolidRun CEX7 Platform"*|"SolidRun LX2160A Honeycomb"*)
      #IMG=honeycomb_lx2160acex7 ;;
      IMG=efi_generic.iso ;;

   # RPi's use a generic Slackware Installer image:
   #"Raspberry Pi 4"*|"Raspberry Pi 3"*)
   "Raspberry Pi"*)
      IMG=rpi_generic.img ;;
esac
[ -z "$IMG" ] && { echo "Can't determine the Hardware Model type" ; exit 1; }

# Append a suffix based on the selected version of Slackware:
#IMG="${AIODIR}/${IMG}-aio-slackware${slkarch}-${slackver}.img"
# We no longer store the release name within the resulting image file name.
# The directory that holds the images carries that responsibility.
IMG="${AIODIR}/${IMG}"

# It may have already been compressed at this point rather than fresh off the
# build machine:
[ -f ${IMG}.xz ] && IMG="${IMG}.xz"
# Sanity check:
[ ! -f $IMG ] && { echo "ERROR: $IMG not found" ; exit 1;}

# Search for the SLKboot partition so we know which MMC to pick.
# No need - use the 'find_sdcard' function so that we can write to
# the SD card, regardless of whether it contains a Slackware 'boot' partition.
#for rdevice in $( ls --indicator-style none /sys/block | grep -Ev "loop|ram|^dm-|^sr|^md" ); do
#   # Is it labeled 'SLKboot' ? if so let's take the first one we find:
#   founddev="$( lsblk -o name,label -ripn /dev/${rdevice} 2>/dev/null | grep -E 'SLKboot$' | awk '{print $1}' )"
#   # Ensure it's an MMC device:
#   [[ "${founddev}" =~ "/dev/mmcblk" ]] && break
#done

# If we didn't find a block device, the user probably isn't running Slackware ARM,
# removed the MMC or relabeled it:
founddev=$( find_sdcard )
[ -z "${founddev}" ] && { echo "ERROR: Unable to determine target block storage device" ; exit 1 ;}

# lop off the partition number so we have the base mmc block device name:
BOOTDEV=${founddev%%p*}

echo "Hardware Model....: $HWM"
echo "A-i-O image.......: $IMG"
echo "Writing to........: $BOOTDEV"

read -p "Ready to umount and write the SD image?"

# Umount the Hardware Model bootware partition if mounted:
#mountpoint -q /boot/platform/hwm_bw && echo is mnt
# We reverse the listing since we need to umount the sub mounts first.
# findmnt also reports them in the correct order, so this works.
mountpoint -q /boot && {
   findmnt -RM /boot -D | grep -E '^/dev' | awk '{print $1}' | tac | while read mntpnt; do
     umount -v $mntpnt || exit 1
   done ;}
sync

echo "Writing $IMG to $BOOTDEV - will be a few mins"
echo "Waiting 10 seconds"
sleep 10

# Handle decompression:
[ "${IMG##*.}" = "xz" ] && furry=xz
# Dump it to the storage and reboot:
#time ${furry}cat $IMG | dd of=$BOOTDEV bs=4M iflag=fullblock status=progress
time ${furry}cat $IMG | dd of=$BOOTDEV bs=8M iflag=fullblock status=progress
sync
read -p "Press ENTER to reboot or CTRL-C to abort"
reboot -f
