#!/usr/bin/env bash
# SPDX-License-Identifier: MIT
# Provision firmware locally; never upload the result to COPR.
set -euo pipefail
usage() {
    printf '%s\n' \
        'Usage: azurefin-extract-firmware SurfaceLaptop7.msi DESTDIR' \
        '       azurefin-extract-firmware --download DESTDIR' \
        '       Prefix either extraction command with --config POLICY.json to select a reviewed firmware release.' \
        '       azurefin-extract-firmware --bluetooth-address MAC [--root ROOT]' \
        'DESTDIR must be a writable image tree with Fedora WCN7850 firmware.' \
        'Downloads use a pinned Microsoft MSI and verify SHA-512 before extraction.' \
        'Bluetooth configuration is saved for the next boot; no service is restarted.' \
        'Do not redistribute the resulting firmware-inclusive image.'
}
script_dir=$(dirname -- "$(realpath -- "$0")")
policy=/usr/share/azurefin/firmware-policy.json
policy_helper=/usr/libexec/azurefin/firmware-policy.py
if [[ -f $script_dir/firmware-policy.py ]]; then
    policy_helper="$script_dir/firmware-policy.py"
    policy="$script_dir/firmware-policy.json"
fi
if [[ ${1:-} == --config ]]; then
    [[ $# -ge 4 ]] || { usage >&2; exit 2; }
    policy=$(realpath -e -- "$2")
    shift 2
fi
if [[ ${1:-} == --help || ${1:-} == -h ]]; then
    usage
    exit 0
fi
if [[ ${1:-} == --bluetooth-address ]]; then
    [[ $# == 2 || ( $# == 4 && $3 == --root ) ]] || { usage >&2; exit 2; }
    address=${2^^}
    [[ $address =~ ^([0-9A-F]{2}:){5}[0-9A-F]{2}$ &&
       $address != 00:00:00:00:00:00 && $address != FF:FF:FF:FF:FF:FF ]] || {
        echo 'Use the factory Bluetooth public address reported by Windows.' >&2
        exit 2
    }
    root=$(realpath -e -- "${4:-/}")
    [[ -d $root/etc && ! -L $root/etc && ! -L $root/etc/romulus-bluetooth-address ]] || {
        echo 'Expected a real etc directory and a non-symlink address file.' >&2
        exit 1
    }
    config="$root/etc/romulus-bluetooth-address"
    if [[ -e $config ]]; then
        cp --backup=numbered -- "$config" "$config.backup"
    fi
    pending=$(mktemp "$root/etc/.romulus-bluetooth-address.XXXXXXXX")
    printf '%s\n' "$address" > "$pending"
    chmod 0644 "$pending"
    mv -fT -- "$pending" "$config"
    echo "Saved Bluetooth address to $config; it will be applied at next boot."
    exit 0
fi
if [[ $# -ne 2 || ( $1 == --* && $1 != --download ) ]]; then
    usage >&2
    exit 2
fi
destination=$(realpath -e -- "$2")
[[ -d $destination/usr/lib/firmware && -w $destination/usr/lib/firmware ]] || {
    echo 'DESTDIR needs writable usr/lib/firmware. Do not modify immutable /usr; provision a local image build instead.' >&2
    exit 1
}
if [[ $(stat -f -c %T "$destination/usr") == erofs ]]; then
    echo 'Cannot provision a running composefs/EROFS deployment; use a writable image build.' >&2
    exit 1
fi
metadata=$(python3 "$policy_helper" "$policy" metadata)
mapfile -t metadata_lines <<< "$metadata"
if [[ $1 == --download ]]; then
    download=$(mktemp -d -t azurefin-download.XXXXXXXX)
    msi="$download/${metadata_lines[0]}"
    echo "Downloading pinned Microsoft firmware installer to $msi"
    curl --fail --location --proto '=https' --proto-redir '=https' --retry 3 \
        --connect-timeout 30 --output "$msi" \
        "${metadata_lines[1]}"
else
    msi=$(realpath -e -- "$1")
fi
python3 "$policy_helper" "$policy" verify-msi "$msi"
work=$(mktemp -d -t azurefin-firmware.XXXXXXXX)
# Keep extraction output on failure for diagnosis; no recursive cleanup trap.
msiextract -C "$work" "$msi"
fw="$destination/usr/lib/firmware"
# Validate every selected blob before copying any of them.
plan=$(python3 "$policy_helper" "$policy" verify-extracted "$work")
while IFS=$'\t' read -r source target; do
    install -Dm644 "$source" "$fw/$target"
done <<< "$plan"
# Patch the distribution's board data locally, never put firmware in this RPM.
board="$fw/ath12k/WCN7850/hw2.0/board-2.bin"
if [[ -f "$board" ]]; then
    cp -- "$board" "$work/board-2.bin"
elif [[ -f "$board.zst" ]]; then
    zstd -dc -- "$board.zst" > "$work/board-2.bin"
elif [[ -f "$board.xz" ]]; then
    xz -dc -- "$board.xz" > "$work/board-2.bin"
else
    echo "Install Fedora's WCN7850 firmware before extracting." >&2
    exit 1
fi
(
    cd "$work"
    /usr/libexec/azurefin/ath12k-bdencoder -e board-2.bin
    /usr/libexec/azurefin/azurefin-board-alias board-2.json
    /usr/libexec/azurefin/ath12k-bdencoder -c board-2.json
)
install -Dm644 "$work/board-2.bin" "$board"
echo "Installed verified firmware. Extraction retained at $work"
