#!/bin/bash
# iKuai x86_64 disaster-recovery upgrader.
# Replaces only the system/boot partition (<boot-disk>1) with a valid official
# x64 .bin payload. It deliberately does not gate on FIRMWAREID/ENTERPRISE.

set -u
umask 077

PROG=${0##*/}
WORKDIR=""

usage() {
    cat >&2 <<EOF
用法: bash $PROG <固件.bin|http://...bin|https://...bin>

可直接运行：wget https://dl.naixi.net/ikuai/ik-upgrade.sh && bash ik-upgrade.sh <固件.bin|URL>

将iKuai官方.bin去掉发布头后写入当前启动盘第1分区。用于售后灾后覆盖系统rootfs，
不检查免费版/企业版、x32/x64、镜像哈希、镜像长度或写后回读。
临时文件保存在/etc/log。
EOF
}

die() { echo "$PROG: $*" >&2; exit 1; }
cleanup() { [ -n "$WORKDIR" ] && rm -rf "$WORKDIR"; }
trap cleanup EXIT HUP INT TERM

[ "$#" = 1 ] || { usage; exit 1; }
SOURCE=$1
[ "$(id -u)" = 0 ] || die "必须以root运行"
. /etc/release
[ -n "${BOOTHDD:-}" ] || die "无法确定启动盘"
TARGET="/dev/${BOOTHDD}1"
[ -b "$TARGET" ] || die "系统分区不存在: $TARGET"
[ -d /etc/log ] && [ -w /etc/log ] || die "/etc/log不可写"

WORKDIR=$(mktemp -d /etc/log/ik-upgrade.XXXXXX) || die "无法创建临时目录"
IMAGE="$WORKDIR/firmware.bin"
PAYLOAD="$WORKDIR/sysupgrade.bin.gz"

case "$SOURCE" in
    http://*|https://*)
        echo "下载固件: $SOURCE"
        curl -fL --connect-timeout 15 --max-time 1800 -o "$IMAGE" "$SOURCE" || die "下载失败"
        ;;
    *)
        [ -f "$SOURCE" ] || die "固件文件不存在: $SOURCE"
        cp "$SOURCE" "$IMAGE"
        ;;
esac

# iKuai .bin开头四字节是发布头长度；固件有效载荷从4+headlen开始。
headhex=$(hexdump -v -n 4 -e '4/1 "%02x"' "$IMAGE")
[ -n "$headhex" ] || die "无法读取固件头"
# BusyBox ash/busybox printf兼容的十六进制转换；不使用16#语法。
headlen=$(printf '%u' "0x$headhex") || die "无法解析固件头"
dd if="$IMAGE" bs=$((headlen + 4)) skip=1 > "$PAYLOAD" 2>/dev/null || die "提取固件载荷失败"

# 有些受损/测试环境把分区节点(/dev/sda1)单独标为只读，但父盘仍可写。
# 写入父盘的该分区起始扇区，字节范围与直接写TARGET完全一致，不触碰MBR或其他分区。
PART_NAME="${BOOTHDD}1"
PART_START_FILE="/sys/class/block/${BOOTHDD}/${PART_NAME}/start"
[ -r "$PART_START_FILE" ] || die "无法读取系统分区起始扇区: $PART_START_FILE"
PART_START=$(cat "$PART_START_FILE")
case "$PART_START" in ''|*[!0-9]*) die "系统分区起始扇区无效: $PART_START";; esac
DISK="/dev/${BOOTHDD}"
[ -b "$DISK" ] || die "启动盘不存在: $DISK"

echo "写入系统分区: $TARGET（通过$DISK第$PART_START扇区）"
gunzip -c "$PAYLOAD" | dd of="$DISK" bs=512 seek="$PART_START" conv=fsync || die "写入失败"
sync
echo "写入完成，请手动执行reboot重启。"
