#!/bin/bash
# SPDX-License-Identifier: MIT

set -e

[ -e /etc/default/update-m1n1 ] && . /etc/default/update-m1n1

[ -n "$M1N1_UPDATE_DISABLED" ] && exit 0

if [ -e "$(dirname "$0")"/functions.sh ]; then
    . "$(dirname "$0")"/functions.sh
else
    . /usr/share/asahi-scripts/functions.sh
fi

: ${M1N1:="/usr/lib/m1n1/m1n1.bin"}
: ${TARGET:="$1"}
: ${DTBS:=$(/bin/ls -d /usr/lib/linux-image-*asahi*/apple 2>/dev/null | sort -rV | head -1)/*.dtb}
: ${CONFIG:=/etc/m1n1.conf}

U_BOOT_DEF="/usr/lib/u-boot/apple_m1/u-boot-nodtb.bin"
U_BOOT_ALT="/usr/lib/u-boot-asahi/u-boot-nodtb.bin"
if [ -z "$U_BOOT" ]; then
    if [ -f "$U_BOOT_DEF" ]; then
        # Use Debian's u-boot as default unless otherwise specified
        U_BOOT="$U_BOOT_DEF"
    elif [ -f "$U_BOOT_ALT" ]; then
        # Most third parties have the u-boot binary at a specific
        # path, different than Debian's. Use it as a fallback to
        # avoid breaking users' systems if it exists, but warn that
        # that they must set U_BOOT explicitly in /etc/default/update-m1n1
        #
        # Note: when this fallback is removed, switch to setting U_BOOT's
        # path via ': ${U_BOOT:=/usr/lib/u-boot/apple_m1/u-boot-nodtb.bin}'
        # and add U_BOOT to the other file checks
        warn "WARNING: Found alternative bootloader (only), please set"
        warn "         U_BOOT=$U_BOOT_ALT"
        warn "         in /etc/default/update-m1n1 or YOUR SYSTEM MIGHT"
        warn "         NOT BOOT in the future!"
        warn
        U_BOOT="$U_BOOT_ALT"
    else
        warn "ERROR: $U_BOOT_DEF not found, will not update m1n1"
        exit 1
    fi
elif [ ! -f "$U_BOOT" ]; then
    warn "ERROR: $U_BOOT not found, will not update m1n1"
    exit 1
fi

if [ ! -f "$M1N1" ]; then
    warn "ERROR: $M1N1 not found, will not update m1n1"
    exit 1
fi

for dtb in $DTBS; do
    if [ ! -f "$dtb" ]; then
        warn "ERROR: DTBs not found, will not update m1n1"
        exit 1
    else
        break
    fi
done

umount=false

m1n1config=/run/m1n1.conf
>"$m1n1config"

if [ -e "$CONFIG" ]; then
    info "Reading m1n1 config from $CONFIG:"
    while read line; do
        case "$line" in
            "") ;;
            \#*) ;;
            chosen.*=*|display=*)
                echo "$line" >> "$m1n1config"
                info "  Option: $line"
                ;;
            *)
                warn "  Ignoring unknown option: $line"
                ;;
        esac
    done <$CONFIG
fi

if [ -z "$TARGET" ]; then
    mount_sys_esp /run/.system-efi
    TARGET="/run/.system-efi/m1n1/boot.bin"
    umount=true
fi

cat "$M1N1" $DTBS >"${TARGET}.new"
gzip -c "$U_BOOT" >>"${TARGET}.new"
cat "$m1n1config" >>"${TARGET}.new"

if [ -e "$TARGET" ]; then
    # clobber "${TARGET}.old" only if "$TARGET" changes, use sha512sum to
    # avoid dependency on diffutils
    SHA512_CUR=$(sha512sum "$TARGET"     | cut -d' ' -f1)
    SHA512_NEW=$(sha512sum "$TARGET.new" | cut -d' ' -f1)
    [ "$SHA512_CUR" != "$SHA512_NEW" ] && mv -f "$TARGET" "${TARGET}.old"
fi

mv -f "${TARGET}.new" "$TARGET"

echo "m1n1 updated at ${TARGET}"
$umount && umount /run/.system-efi
true
