#!/bin/bash
#
# NOTE: This script is used on legacy-flash boards and runs with busybox ash,
# not bash
set -e -o pipefail
. /etc/functions.sh
. /tmp/config

TRACE_FUNC

case "$CONFIG_FLASH_OPTIONS" in
  "" )
    DIE "ERROR: No flash options have been configured!\n\nEach board requires specific CONFIG_FLASH_OPTIONS options configured. It's unsafe to flash without them.\n\nAborting."
  ;;
  * )
    DEBUG "Flash options detected: $CONFIG_FLASH_OPTIONS"
    INFO "Board $CONFIG_BOARD detected with flash options configured"
  ;;
esac

flash_rom() {
  ROM=$1
  if [ "$READ" -eq 1 ]; then
    $CONFIG_FLASH_OPTIONS -r "${ROM}" \
    || recovery "Backup to $ROM failed"
  else
    STATUS "Preparing new ROM image for flashing"
    cp "$ROM" /tmp/${CONFIG_BOARD}.rom
    STATUS "Verifying SHA-256 checksum of ROM image"
    sha256sum /tmp/${CONFIG_BOARD}.rom
    if [ "$CLEAN" -eq 0 ]; then
      # preserve_rom copies heads/ runtime config files (GPG keyring,
      # TOTP/HOTP secrets, LUKS DUK slot data, runtime settings) from
      # the currently running ROM's CBFS into the new ROM image before
      # flashing.  These files would otherwise be lost on each firmware
      # update.  Skip with -c (clean flash) flag.
      DEBUG "flash_rom: CLEAN=$CLEAN — preserving heads/ CBFS files"
      preserve_rom /tmp/${CONFIG_BOARD}.rom \
      || recovery "$ROM: Config preservation failed"
    else
      DEBUG "flash_rom: CLEAN=$CLEAN — skipping config preservation (clean flash)"
    fi
    # persist serial number from CBFS
    if cbfs.sh -r serial_number > /tmp/serial 2>/dev/null; then
      STATUS "Persisting system serial"
      cbfs.sh -o /tmp/${CONFIG_BOARD}.rom -d serial_number 2>/dev/null || true
      cbfs.sh -o /tmp/${CONFIG_BOARD}.rom -a serial_number -f /tmp/serial
    fi
    # persist PCHSTRP9 from flash descriptor
    if [ "$CONFIG_BOARD" = "librem_l1um" ]; then
      STATUS "Persisting PCHSTRP9"
      $CONFIG_FLASH_OPTIONS -r /tmp/ifd.bin --ifd -i fd >/dev/null 2>&1 \
      || DIE "Failed to read flash descriptor"
      dd if=/tmp/ifd.bin bs=1 count=4 skip=292 of=/tmp/pchstrp9.bin >/dev/null 2>&1
      dd if=/tmp/pchstrp9.bin bs=1 count=4 seek=292 of=/tmp/${CONFIG_BOARD}.rom conv=notrunc >/dev/null 2>&1
    fi

    WARN "Do not power off computer.  Updating firmware, this will take a few minutes"
    STATUS "Flashing ROM to chip"
    $CONFIG_FLASH_OPTIONS -w /tmp/${CONFIG_BOARD}.rom 2>&1 \
      || recovery "$ROM: Flash failed"
    STATUS_OK "ROM flashed successfully"
  fi
}

if [ "$1" == "-c" ]; then
  CLEAN=1
  READ=0
  ROM="$2"
elif [ "$1" == "-r" ]; then
  CLEAN=0
  READ=1
  ROM="$2"
  touch $ROM
else
  CLEAN=0
  READ=0
  ROM="$1"
fi

if [ ! -e "$ROM" ]; then
    DIE "Usage: $0 [-c|-r] <path/to/image.(rom|tgz)>"
fi

if [ "$READ" -eq 0 ] && [ "${ROM##*.}" = tgz ]; then
    if [ "${CONFIG_BOARD%_*}" = talos-2 ]; then
        rm -rf /tmp/verified_rom
        mkdir /tmp/verified_rom

        tar -C /tmp/verified_rom -xf $ROM || DIE "Rom archive $ROM could not be extracted"
    if ! (cd /tmp/verified_rom/ && sha256sum -cs sha256sum.txt); then
            DIE "Provided tgz image did not pass hash verification"
        fi

        STATUS "Reading current flash and building update image"
        $CONFIG_FLASH_OPTIONS -r /tmp/flash.sh.bak \
            || recovery "Read of flash has failed"

        # ROM and bootblock already have ECC
        bootblock=$(echo /tmp/verified_rom/*.bootblock)
        rom=$(echo /tmp/verified_rom/*.rom)
        kernel=$(echo /tmp/verified_rom/*-zImage.bundled)
        pnor /tmp/flash.sh.bak -aw HBB < $bootblock
        pnor /tmp/flash.sh.bak -aw HBI < $rom
        pnor /tmp/flash.sh.bak -aw BOOTKERNEL < $kernel
        rm -rf /tmp/verified_rom

        ROM=/tmp/flash.sh.bak
    else
        DIE "$CONFIG_BOARD doesn't support tgz image format"
    fi
fi

flash_rom $ROM

# don't leave temporary files lying around
rm -f /tmp/flash.sh.bak

exit 0
