#!/bin/sh
# Scutarius finish-install hook for SBC targets (installed as
# /usr/lib/finish-install.d/07scutarius-sbc by the arch_tree rule).
# Spec: docs/superpowers/specs/2026-08-24-installer-sbc-media-design.md S9/S10.
# Board-conditional on the device-tree compatible; no-op elsewhere (GB10 is
# ACPI/DMI, no /proc/device-tree).
. /usr/share/debconf/confmodule

COMPAT=$(tr '\0' '\n' < /proc/device-tree/compatible 2>/dev/null | head -1)
# The org's choice for boards whose firmware it builds (org.schema
# ENABLE_SECURE_BOOT_ON_SUPPORTED_HOSTS: true | false | ask), rendered into this
# file when the installer source is assembled.
SB_POLICY="true"
log() { logger -t scutarius-sbc "$@" 2>/dev/null || echo "scutarius-sbc: $@" >&2; }
# spi_failed <reason>: log it AND show it. Every way the firmware write can
# fail or be skipped (except the user declining) reaches the screen: on
# 2026-09-17 a failed checksum check was only logged, the install finished
# looking successful, and the board was left without firmware in SPI.
spi_failed() {
  log "rk3588: SPI not written: $1"
  db_subst scutarius/sbc-spi-failed reason "$1" || true
  db_fset scutarius/sbc-spi-failed seen false || true
  db_input critical scutarius/sbc-spi-failed || true
  db_go || true
  exit 0
}

# Runtime-loaded templates (this hook owns no udeb templates file).
TPL=/tmp/scutarius-sbc.templates
cat > $TPL <<'EOT'
Template: scutarius/sbc-flash-spi
Type: boolean
Default: true
Description: Write this distribution's UEFI firmware to SPI NOR now?
 The installed system boots through the board's SPI NOR firmware. Writing the
 edk2-rk3588 image built for this distribution makes the board boot the
 installed system without the installation media, with this distribution's
 Secure Boot keys. The firmware's stored settings are kept. Only decline to
 keep the firmware the board has now.

Template: scutarius/sbc-secure-boot
Type: boolean
Default: true
Description: Turn on UEFI Secure Boot on this board?
 The firmware about to be written to this board comes in two versions. With
 Secure Boot on, the board starts only boot loaders and kernels signed with
 keys this distribution trusts. With it off, the board starts anything, and
 Secure Boot can still be turned on later from the firmware setup by
 enrolling the built-in default keys.

Template: scutarius/sbc-no-firmware
Type: note
Description: Board firmware not written
 This board boots through UEFI firmware in its SPI NOR, and the firmware built
 for this distribution was not installed, so the SPI NOR was left as it is.
 ${reason}
 .
 The installed system boots only if the board already has working UEFI
 firmware. To write it later from the installed system: enable the
 non-free-firmware component, install task-scutarius-rock-5b, then run
 flash-rk3588-edk2-spi.

Template: scutarius/sbc-spi-failed
Type: note
Description: Board firmware NOT written
 The UEFI firmware for this board was not written to its SPI flash:
 .
 ${reason}
 .
 The installed system boots only if the board already has working UEFI
 firmware. The firmware can be written later from the installed system with
 flash-rk3588-edk2-spi (package scutarius-firmware-rk3588-edk2).

Template: scutarius/sbc-wipe-sd
Type: boolean
Default: true
Description: Remove the installer from the SD card (keep u-boot)?
 This board has no SPI flash: the SD card remains the permanent home of
 u-boot, which scans the SD card first at every boot. Wiping the installer
 payload (everything after the first 16 MB) lets u-boot fall through to the
 system installed on NVMe. Only decline to keep the card as installer media.
EOT
debconf-loadtemplate scutarius $TPL || true

# Boards in the installer's board table (/usr/share/scutarius/sbc-boards, patch
# 0018); the 4C+ below predates the table and keeps its own match.
. /usr/lib/scutarius/sbc-lib
IN_TABLE=
sbc_board && IN_TABLE=1

# console=dt: the installed kernel's console arguments. Without them the device
# tree's stdout-path makes the SERIAL port /dev/console, so the LUKS passphrase
# prompt never reaches the screen (ROCK 5B, 2026-09-17). Serial first, tty0
# last: the last console= is /dev/console. Done here, after grub-installer,
# directly in the target's /etc/default/grub, and only when the admin line has
# no console= yet.
if [ "$IN_TABLE" ] && [ "$SBC_CONSOLE" = dt ]; then
  args=$(sbc_console_args)
  G=/target/etc/default/grub
  if [ -z "$args" ]; then
    log "$COMPAT: no usable device-tree stdout-path; kernel console arguments not set"
  elif [ -f "$G" ] && ! grep -q '^GRUB_CMDLINE_LINUX=.*console=' "$G"; then
    cur=$(sed -n 's/^GRUB_CMDLINE_LINUX="\(.*\)"$/\1/p' "$G")
    sed -i "s|^GRUB_CMDLINE_LINUX=.*|GRUB_CMDLINE_LINUX=\"${cur:+$cur }$args\"|" "$G"
    in-target update-grub >/dev/null 2>&1 \
      && log "$COMPAT: kernel console arguments '$args' set" \
      || log "$COMPAT: kernel console arguments set in /etc/default/grub, but update-grub FAILED"
  fi
fi

case "${IN_TABLE:+board-table}" in
  board-table)
    # S9: write UEFI firmware to SPI NOR so the installed system boots without
    # the installation media.
    #
    # THE IMAGE IS PER BOARD and is the one BUILT FOR THIS DISTRIBUTION
    # (scutarius-firmware-rk3588-edk2), never an upstream release: writing an
    # upstream image over it would drop its Secure Boot keys. Match the
    # compatible exactly -- a glob like radxa,rock-5b* also matches the 5B+, a
    # different machine whose wrong bootloader in SPI is recoverable only
    # through maskrom and another computer -- and skip a board the package has
    # no image for.
    IMGDIR=/target/usr/share/scutarius-firmware-rk3588-edk2
    [ "$SBC_FIRMWARE" != - ] || spi_failed "This distribution has no firmware image for this board ($COMPAT) yet."
    BOARD=$SBC_FIRMWARE
    # The image comes ONLY from task-scutarius-rock-5b, which the software step
    # installs when non-free-firmware is enabled (scutarius-tasks pre-pkgsel
    # hook). This step installs nothing itself: adding a package, or a
    # component, the user did not choose is not its business. Say why instead.
    if [ ! -f "$IMGDIR/SHA256SUMS" ]; then
      db_get apt-setup/non-free-firmware || true
      if [ "$RET" = true ]; then
        why="The package scutarius-firmware-rk3588-edk2 ($SBC_TASK) did not get installed; the installation log has the reason."
      else
        why="It is in the non-free-firmware component, which was not enabled for this installation."
      fi
      log "rk3588: firmware package not in /target ($COMPAT); SPI not written: $why"
      db_subst scutarius/sbc-no-firmware reason "$why" || true
      db_input critical scutarius/sbc-no-firmware || true
      db_go || true
      exit 0
    fi
    # Two images per board, Secure Boot on or off; the org setting picks, or
    # the installer asks (default: on).
    case "$SB_POLICY" in
      true)  SB=true ;;
      false) SB=false ;;
      ask)
        db_input critical scutarius/sbc-secure-boot || true
        db_go || true
        db_get scutarius/sbc-secure-boot; SB=$RET ;;
      *) spi_failed "This installer carries an invalid Secure Boot setting ('$SB_POLICY')." ;;
    esac
    if [ "$SB" = true ]; then IMGNAME=$BOARD-secureboot.img; else IMGNAME=$BOARD-nosecureboot.img; fi
    IMG=$IMGDIR/$IMGNAME
    [ -f "$IMG" ] || spi_failed "The firmware package has no $IMGNAME."
    # The SPI NOR chip driver is a module and nothing else pulls mtdblock in.
    modprobe -q mtd 2>/dev/null || true
    modprobe -q spi-nor 2>/dev/null || true
    modprobe -q mtdblock 2>/dev/null || true
    n=0; while [ ! -c /dev/mtd0 ] && [ $n -lt 5 ]; do sleep 1; n=$((n+1)); done
    [ -c /dev/mtd0 ] || spi_failed "The SPI flash was not detected (no /dev/mtd0)."
    db_input critical scutarius/sbc-flash-spi || true
    db_go || true
    db_get scutarius/sbc-flash-spi
    [ "$RET" = true ] || { log "rk3588: SPI write declined"; exit 0; }
    # Checksum against the package's SHA256SUMS, with what busybox's
    # sha256sum supports: it has no --ignore-missing, and using it made this
    # check fail on every install (2026-09-17).
    want=$(grep " $IMGNAME\$" "$IMGDIR/SHA256SUMS" 2>/dev/null | cut -c1-64)
    got=$(sha256sum "$IMG" | cut -c1-64)
    [ -n "$want" ] && [ "$got" = "$want" ] || spi_failed "The firmware image $IMGNAME does not match its checksum (expected ${want:-none listed}, got $got)."
    # flashcp comes from mtd-utils, a dependency of the same task.
    in-target sh -c 'command -v flashcp' >/dev/null 2>&1 || spi_failed "flashcp is not installed in the new system (package mtd-utils)."
    in-target flashcp -v "/usr/share/scutarius-firmware-rk3588-edk2/$IMGNAME" /dev/mtd0 \
      || spi_failed "flashcp reported an error while writing $IMGNAME. The SPI flash contents are unknown: keep the installation media."
    # Read the SPI back over the image's length and compare, independently of
    # flashcp's own verify pass.
    size=$(wc -c < "$IMG")
    back=$(head -c "$size" /dev/mtd0 | sha256sum | cut -c1-64)
    [ "$back" = "$got" ] || spi_failed "The SPI flash does not read back as $IMGNAME after writing (read back $back). Keep the installation media."
    log "rk3588: SPI NOR written and read back ($IMGNAME, $size bytes, Secure Boot $SB)"
    ;;
esac

case "$COMPAT" in
  radxa,rock-pi-4c-plus*|radxa,rock-4c-plus*)
    # S10: SD stays (holds u-boot, no SPI on this board); remove the
    # installer payload so u-boot falls through to NVMe.
    SD=""
    for d in /dev/mmcblk0 /dev/mmcblk1; do [ -b "$d" ] && { SD=$d; break; }; done
    [ -n "$SD" ] || { log "4c+: no mmcblk device found; SD not wiped"; exit 0; }
    # never touch the disk we just installed to
    TROOT=$(mount | sed -n 's,^\(/dev/[a-z0-9]*\)[0-9p]* on /target .*,\1,p' | head -1)
    [ "$TROOT" = "$SD" ] && { log "4c+: target root is on $SD; SD not wiped"; exit 0; }
    db_input critical scutarius/sbc-wipe-sd || true
    db_go || true
    db_get scutarius/sbc-wipe-sd
    [ "$RET" = true ] || { log "4c+: SD wipe declined"; exit 0; }
    # blank the partition table copies and everything past 16 MiB;
    # bytes 512..16MiB (idbloader @32KiB, u-boot.itb @8MiB) are preserved.
    SIZE=$(blockdev --getsz "$SD")
    dd if=/dev/zero of="$SD" bs=512 count=1 conv=notrunc 2>/dev/null           # MBR/PMBR
    dd if=/dev/zero of="$SD" bs=512 seek=1 count=63 conv=notrunc 2>/dev/null   # GPT hdr+entries area (idbloader starts at 64)
    dd if=/dev/zero of="$SD" bs=512 seek=$((SIZE-34)) count=34 conv=notrunc 2>/dev/null  # backup GPT
    dd if=/dev/zero of="$SD" bs=1M seek=16 count=64 conv=notrunc 2>/dev/null   # installer FAT start
    log "4c+: SD installer payload wiped; u-boot (first 16 MiB) preserved"
    ;;
  *)
    exit 0 ;;
esac
exit 0
