#!/bin/sh
# Загрузчик на всех ESP системных дисков узла = /boot/loader.efi (после update.sh, до перезагрузки).
# update.sh обновляет только ESP, с которого узел загрузился (BootCurrent); на втором диске зеркала
# остаётся прежний загрузчик, и при отказе первого диска узел поднимется с него.
#   sh esp-sync.sh          — проверка: что отличается (ничего не пишет)
#   sh esp-sync.sh apply    — записать (старые файлы -> *.prev)
# Итог: строка "ESP OK" (код 0) или "ESP DIFF"/"ESP FAIL" (код 1/2).
MODE=${1:-check}
NEW=/boot/loader.efi
[ -r $NEW ] || { echo "ESP FAIL: нет $NEW"; exit 2; }
H=$(sha256 -q $NEW); rc=0; n=0
# диски, на которых лежит корень: компоненты gmirror или устройство, смонтированное в /
ROOTDEV=$(mount -p | awk '$2=="/" {print $1}' | sed 's|^/dev/||')
case $ROOTDEV in
  mirror/*) PARTS=$(gmirror list ${ROOTDEV#mirror/} | awk '/^[0-9]+\. Name: / {print $3}') ;;
  gpt/*|label/*|ufs/*) PARTS=$(glabel status -s | awk -v l="$ROOTDEV" '$1==l {print $3}') ;;
  *) PARTS=$ROOTDEV ;;
esac
DISKS=$(for x in $PARTS; do echo $x | sed -E 's/p[0-9]+$//; s/s[0-9]+[a-h]?$//'; done | sort -u)
[ -n "$DISKS" ] || { echo "ESP FAIL: не определить системные диски (корень $ROOTDEV)"; exit 2; }
echo "корень: $ROOTDEV, системные диски: $(echo $DISKS)"
for P in $(for d in $DISKS; do gpart show -p $d 2>/dev/null | awk '$4=="efi" {print $3}'; done); do
  n=$((n+1))
  MP=$(mount -p | awk -v d="/dev/$P" '$1==d {print $2}')
  [ -z "$MP" ] && MP=$(for l in $(glabel status -s 2>/dev/null | awk -v p="$P" '$3==p {print $1}'); do mount -p | awk -v d="/dev/$l" '$1==d {print $2}'; done | head -1)
  TMP=""
  if [ -z "$MP" ]; then
    TMP=$(mktemp -d /tmp/esp.XXXX); opt=ro; [ "$MODE" = apply ] && opt=rw
    mount -t msdosfs -o $opt /dev/$P $TMP || { echo "$P: не смонтировать"; rc=2; rmdir $TMP; continue; }
    MP=$TMP
  fi
  for F in $(find $MP -type f \( -iname loader.efi -o -iname bootx64.efi \) | grep -i -E '/efi/(freebsd|boot)/'); do
    h=$(sha256 -q $F)
    if [ "$h" = "$H" ]; then echo "$P ${F#$MP}: ok"; continue; fi
    if [ "$MODE" = apply ]; then
      cp -p $F $F.prev && cp $NEW $F.new && mv $F.new $F && sync && [ "$(sha256 -q $F)" = "$H" ] \
        && echo "$P ${F#$MP}: обновлён (прежний — ${F#$MP}.prev)" || { echo "$P ${F#$MP}: ОШИБКА записи"; rc=2; }
    else
      echo "$P ${F#$MP}: ОТЛИЧАЕТСЯ ($h)"; [ $rc = 0 ] && rc=1
    fi
  done
  [ -n "$TMP" ] && { umount $TMP; rmdir $TMP; }
done
[ $n -gt 0 ] || { echo "ESP FAIL: разделов efi не найдено"; exit 2; }
case $rc in 0) echo "ESP OK ($n раздел(а), $H)";; 1) echo "ESP DIFF";; *) echo "ESP FAIL";; esac
exit $rc
