#!/bin/sh
# SPDX-License-Identifier: GPL-3.0+
# Copyright 2024-2025 Johannes Schauer Marin Rodrigues <josch@mister-muffin.de>
#
# Populate /boot with all known dtbs.
# The flash-kernel package is still needed to provide the /boot/dtb-$(uname -r)
# symlink. That symlink is needed on platforms that do not set the `${fdtfile}`
# u-boot environment variable.

set -e

self="$0"
version="$1"
# shellcheck disable=SC2034
image_path="$2"

# linux-run-hooks from src:linux-base runs run-parts with --report which only
# prints the name of the scripts it runs *if* the script in question produces
# any output. Scripts that do not produce any output do not get an indication
# by run-parts that they got run. So we print early to make sure that we are
# able to easily see if this script was run or not during a given installation.
echo "I: Now running: $0 $*" >&2
echo "I: with DEB_MAINT_PARAMS=$DEB_MAINT_PARAMS" >&2

# shellcheck disable=SC2086
set -- $DEB_MAINT_PARAMS

# strip single quotes from beginning and end
action="${1#\'}"
action="${action%\'}"

set -u

dtb_required() {
  config="$1"
  if [ ! -e /proc/device-tree/model ]; then
    return 1
  fi
  if [ -z "$(cat /proc/device-tree/model)" ]; then
    return 1
  fi
  if [ "$(cat /proc/device-tree/model)" != "$(basename "$config" .conf)" ]; then
    return 1
  fi
  return 0
}

install_dtbs() {
  if [ -d "/usr/lib/modules/$version/dtb" ]; then
    # this should be kernels >= 6.18
    DT_INSTALL_DIR="/usr/lib/modules/$version/dtb"
  elif [ -L "/usr/lib/linux-image-$version" ]; then
    # kernel >= 6.18 ship modules in /usr/lib/modules/$version/dtb and the
    # old location is a compatibility symlink
    if [ -d "/usr/lib/linux-image-$version" ]; then
      DT_INSTALL_DIR="/usr/lib/linux-image-$version"
    else
      echo "E: Neither /usr/lib/modules/$version/dtb nor /usr/lib/linux-image-$version do exist" >&2
      exit 1
    fi
  elif [ -d "/usr/lib/linux-image-$version" ]; then
    # we are likely before kernel 6.18
    DT_INSTALL_DIR="/usr/lib/linux-image-$version"
  else
    echo "E: Neither /usr/lib/modules/$version/dtb nor /usr/lib/linux-image-$version do exist" >&2
    exit 1
  fi
  for CONF in /usr/share/reform-tools/machines/*.conf; do
    # shellcheck disable=SC1090
    . "$CONF"
    # run find with -H in case DT_INSTALL_DIR is a symlink
    dtb=$(find -H "$DT_INSTALL_DIR" -wholename "*/$DTBPATH" 2>/dev/null | head -n 1)
    if [ -z "$dtb" ]; then
      if dtb_required "$CONF"; then
        echo "E: no dtb for $DTBPATH in $DT_INSTALL_DIR but is required for this platform" >&2
        exit 1
      else
        echo "W: no dtb for $DTBPATH in $DT_INSTALL_DIR -- skipping..." >&2
        continue
      fi
    elif [ ! -f "$dtb" ]; then
      if dtb_required "$CONF"; then
        echo "E: $dtb does not exist but is required for this platform" >&2
        exit 1
      else
        echo "W: $dtb does not exist -- skipping..." >&2
        continue
      fi
    fi
    if [ ! -e "$DT_INSTALL_DIR/$DTBPATH" ]; then
      echo "W: irregular dtb path: $dtb" >&2
    fi
    mkdir -p "/boot/dtbs/$version/$(dirname "$DTBPATH")"
    echo "I: copying $dtb to /boot/dtbs/$version/$DTBPATH" >&2
    cp "$dtb" "/boot/dtbs/$version/$DTBPATH"
  done
}

remove_dtbs() {
  for CONF in /usr/share/reform-tools/machines/*.conf; do
    # shellcheck disable=SC1090
    . "$CONF"
    rm -f "/boot/dtbs/$version/$DTBPATH" || :
  done
  rmdir --ignore-fail-on-non-empty "/boot/dtbs/$version"
}

case "$self:$action" in
  # Only run on postinst configure and postrm remove, to avoid wasting
  # time by calling this script multiple times on upgrade and removal.
  */postinst.d/*:configure) install_dtbs ;;
  */postrm.d/*:remove) remove_dtbs ;;
  *) exit 0 ;;
esac
