#!/bin/bash
set +o posix
shopt -s extglob

###############################################################################
# Script : slackwareaarch64-<ver>/source/a/hwm-bw-lx2160acex7/sources/store-fw
# Purpose: Process and store the firmware for the Solid Run lx2160acex7
#          Hardware Models.
# Author : Stuart Winter <mozes@slackware.com>
# Date...: 14-Oct-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.

# Load the Slackware ARM dev kit:
source /usr/share/slackdev/buildkit.sh

CWD=$PWD
fullfwdir=$CWD/firmware-full
# The SPI firmware lives within source/a/hwm-bw-lx2160acex7:
fwdir_spi=$CWD/firmware_spi
# The bootable SD card images live within the 'platform' directory outside of
# the Slackware tree:
fwdir_sd=$SLACKPLATFORMDIR/bootware/recovery/lx2160acex7

rm -rf ${fwdir_spi}
mkdir -vpm755 ${fwdir_spi}

# A single checksum file for all known firmware is shipped within the
# 'a/hwm-bw-lx2160acex7' package:
chksummanifest=${fwdir_spi}/checksums

# Generate a list of unique build profiles from the list of
# firmware files, then move the most recent into place:
function copy_latest_fw() {
   local fwfile
   local outdir=$1
   while read fwfile; do
      # Move the most recent version (according to the last modification time) into place:
      mv -fv $( find . -name "${fwfile}*" -type f -printf "%f %T@\n" | sort -k2 | tail -n1 | awk '{print $1}' ) ${outdir}/
   done< <( find . -type f -mindepth 1 -maxdepth 1 -name '*img*' -printf "%f\n" | cut -d_ -f1-7 | sort | uniq )
}

# Clean the SoC's platform directory apart from the README.txt
pushd ${fwdir_sd} || exit 1
rm -vf !(*README*)
popd

# Obtain the last modification date:
# stat --printf "%Y\n" lx2160acex7_2000_700_3200_8_5_2_flexspi_nor_ee5c233.img.xz
# stat --printf "%y\n" lx2160acex7_2000_700_3200_8_5_2_flexspi_nor_ee5c233.img.xz

# Sort the image types:
# Enter the directory containing the SD card and SPI NOR images:
pushd $fullfwdir || exit 1
mkdir sdcard spi
mv -fv *_sd_* sdcard/
mv -fv *flexspi_nor_* spi/

# Determine the most recent firmware images:
# SD cards:
pushd sdcard
copy_latest_fw ${fwdir_sd}
popd
# SPI flash:
pushd spi
copy_latest_fw ${fwdir_spi}
popd

popd

# Create a manifest of the checksums of the first 100K of each file.
# This is (more than) sufficient to compare the firmware within the
# SPI flash against what's in our package:
function sumfw() {
   local fwdir=$1
   local manifest=$2

   pushd $fwdir
   mkdir unpacked
   cp -fa *img* unpacked/
   pushd unpacked
   while read fwfile; do
     echo "Checksumming: ${fwfile}"
     # Unpack so we can checksum it:
     xz -d ${fwfile} || exit 1
     echo "${fwfile}:$( dd status=none bs=4k count=100k iflag=count_bytes if=${fwfile%.xz} | md5sum | awk '{print $1}' )" >> ${manifest}
   done< <( find . -type f -mindepth 1 -maxdepth 1 -printf "%f\n" )
   popd
   rm -rf unpacked
   popd
}

cat << EOF > ${chksummanifest}
# Note: This is only the md5sum of the _first_ 100K of each file.
# This is to avoid reading so much data from the SPi flash when discovering
# which version of the firmware is installed.
EOF

# Generate checksums of the firmware we're shipping:
sumfw ${fwdir_spi} ${chksummanifest}
# Generate checksums of the rest of the firmware binaries.
# We use this to determine if someone has an older release (as long as it's
# of SolidRun's official binary releases) of the firmware within their SPI flash.
# If so, we can determine what their hardware profile setting is based on
# the file name.

# Generate checksums of older SPI images:
cat << EOF >> ${chksummanifest}
# Here follows the checksums for firmware that we don't ship.  These allow us
# to discover the hardware configuration profile when a known (but perhaps old)
# version of the firmware is available:
EOF
sumfw ${fullfwdir}/spi ${chksummanifest}

# Generate checksums of the most recent SD card images that we're
# shipping with Slackware.
cat << EOF >> ${chksummanifest}
# Here follows the checksums for firmware that may be present on the SD card.
# These are shipped with Slackware.
# These allow us to discover the hardware configuration profile during the
# initial installation of Slackware:
EOF
sumfw ${fwdir_sd} ${chksummanifest}

# Generate checksums of the older release of the SD card images
# that we're not shipping, but that users could realistically boot with:
cat << EOF >> ${chksummanifest}
# The following checksums are for firmware releases that are available
# from the vendor, but that Slackware does not ship.
EOF
sumfw ${fullfwdir}/sdcard ${chksummanifest}


# Compress the checksums:
xz -ze9 ${chksummanifest}

# For the SD card firmware images, create symlinks that can be referenced
# from the Install guides:
pushd ${fwdir_sd} || exit 1
while read fwfile ; do
  ln -vfs ${fwfile} "$( echo ${fwfile} | sed 's/_sd_.*.img.xz$//' )".img.xz
done< <( find . -type f -name '*img*' -printf "%f\n" )
popd
