#!/bin/sh
# fix_validate.sh -- DF-2553 A/B fix validation (host side).  As actually run.
#
# 1. vm.sh reset with-src            (clean source snapshot, stock kernel)
# 2. re-push harness + conf/files entry, verify pristine subr_sbuf.c sha
# 3. patch -p1 < fix.diff            (the ONLY functional change)
# 4. make nativekernel + installkernel + reboot
# 5. rerun the exact PoC modes       (log -> fix_run.log)
#    expect: mode 1 -> *error=22 EINVAL, uio untouched (0 bytes copied),
#            corrupted=0; mode 0 output byte-identical to baseline.
set -eu
PACK="$(cd "$(dirname "$0")" && pwd)"
ROOT="$(cd "$PACK/../../.." && pwd)"
VM="$ROOT/dfbsd-qemu/vm.sh"
SSHCFG="$ROOT/dfbsd-qemu/config"

echo "== reset guest to clean-source snapshot"
"$VM" reset with-src

echo "== verify pristine subr_sbuf.c and re-push harness"
GUEST_SHA=$("$VM" run_root 'sha256 -q /usr/src/sys/kern/subr_sbuf.c' | tail -1)
echo "guest sha: $GUEST_SHA (expect 854fe3f4bf6e5b10d09e503c24304dbc432ffad83a3d67c7c8f54699741ac44e)"
scp -q -F "$SSHCFG" "$PACK/kern_df2553.c" dfbsd:/usr/src/sys/kern/kern_df2553.c
scp -q -F "$SSHCFG" "$PACK/df2553_trigger.c" dfbsd:/root/df2553_trigger.c
"$VM" run_root 'grep -q kern_df2553 /usr/src/sys/conf/files || printf "kern/kern_df2553.c\tstandard\n" >> /usr/src/sys/conf/files'

echo "== apply fix.diff and rebuild (log -> fix_build.log)"
scp -q -F "$SSHCFG" "$PACK/fix.diff" dfbsd:/root/fix.diff
"$VM" run_root 'cd /usr/src && patch -p1 < /root/fix.diff && grep -c 0x7ffffffe sys/kern/subr_sbuf.c' || exit 1
"$VM" run_root 'cd /usr/src && make -j6 nativekernel KERNCONF=X86_64_GENERIC && make installkernel KERNCONF=X86_64_GENERIC' \
	> "$PACK/fix_build.log" 2>&1 || { tail -40 "$PACK/fix_build.log" >&2; exit 1; }
"$VM" run_root 'shutdown -r now' || true
i=0
while [ "$i" -lt 150 ]; do
	sleep 5; i=$((i+5))
	"$VM" run_root 'true' >/dev/null 2>&1 && { echo "back after ${i}s"; break; }
done

echo "== rerun exact PoC on patched kernel (log -> fix_run.log)"
"$VM" run_root 'cc -O2 -Wall -o /root/df2553_trigger /root/df2553_trigger.c && dmesg -c >/dev/null 2>&1; /root/df2553_trigger 2 >/dev/null; /root/df2553_trigger 1 >/dev/null; /root/df2553_trigger 0 >/dev/null; /root/df2553_trigger 1 >/dev/null; dmesg | grep DF2553' \
	| tee "$PACK/fix_run.log"
