#!/bin/sh
# make_fixed.sh -- A/B fix build: replace the guest's amd.c with a
# copy of the audit-tree amd.c carrying BOTH fixes (this pack's
# fix.diff and the sibling DF-2426/DF-2427 pack's fix.diff; they touch
# different functions of the same file, so one fixed kernel validates
# both findings), regenerate the harness TU and rebuild (quickkernel),
# install, reboot.
#
# The fixes are applied on the AUDIT HOST from the two fix.diffs --
# sequentially (a concatenated both.diff makes patch(1) misparse the
# second header as reversed) and never with interactive patch(1) on
# the guest.  The audit-side sys/ tree is never touched; amd.c.orig on
# the guest keeps the pristine file for the sha256 verbatim gate.
set -e
cd "$(dirname "$0")"
ROOT=/home/maxx/dfbsd/dfbsd
CFG=$ROOT/dfbsd-qemu/config
SSH="ssh -F $CFG -o ConnectTimeout=8 -o BatchMode=yes dfbsd"
SCP="scp -F $CFG -o ConnectTimeout=8 -o BatchMode=yes"
HERE=$(pwd)
if [ "$(basename "$HERE")" = DF-2426 ]; then
	SIB="$HERE/../DF-2427"
else
	SIB="$HERE/../DF-2426"
fi
rsh() { printf '%s\n' "$1" | $SSH /bin/sh; }

# ---- build amd.fixed = pristine audit-tree amd.c + both fix.diffs ----
WORK=$(mktemp -d)
mkdir -p "$WORK/sys/dev/disk/amd"
cp "$ROOT/sys/dev/disk/amd/amd.c" "$WORK/sys/dev/disk/amd/amd.c"
(cd "$WORK" && patch -sp0 --batch --forward < "$HERE/fix.diff" && \
    patch -sp0 --batch --forward < "$SIB/fix.diff")
grep -q cam_calc_geometry "$WORK/sys/dev/disk/amd/amd.c"
grep -q "Invalid reselection" "$WORK/sys/dev/disk/amd/amd.c"
cp "$WORK/sys/dev/disk/amd/amd.c" amd.fixed
sha256sum amd.fixed | awk '{print $1}' > amd.fixed.sha256
echo "amd.fixed built ($(wc -l < amd.fixed) lines, sha256 $(cat amd.fixed.sha256))"
rm -rf "$WORK"

$ROOT/dfbsd-qemu/vm.sh status >/dev/null

# restore pristine .orig, install the fixed amd.c
$SCP "$ROOT/sys/dev/disk/amd/amd.c" dfbsd:/usr/src/sys/dev/disk/amd/amd.c.orig
$SCP amd.fixed dfbsd:/usr/src/sys/dev/disk/amd/amd.c
rsh 'sha256 -q /usr/src/sys/dev/disk/amd/amd.c /usr/src/sys/dev/disk/amd/amd.c.orig'
rsh 'sh /root/gen_amd.sh' > gen_fixed.log 2>&1
cat gen_fixed.log

echo '=== quickkernel (detached on the guest) ==='
rsh 'rm -f /root/build.ok /root/build.fail /root/build.log'
rsh 'cd /usr/src && nohup make -j6 quickkernel KERNCONF=X86_64_GENERIC > /root/build.log 2>&1 < /dev/null && touch /root/build.ok || touch /root/build.fail' \
    > /dev/null 2>&1 &
i=0
while [ $i -lt 2400 ]; do
	sleep 10
	if rsh 'test -f /root/build.ok || test -f /root/build.fail' 2>/dev/null; then
		break
	fi
	i=$((i + 10))
	if [ $((i % 120)) -eq 0 ]; then echo "... building (${i}s)"; fi
done
$SCP dfbsd:/root/build.log fix_build.log
if ! rsh 'test -f /root/build.ok' 2>/dev/null; then
	echo 'FIX BUILD FAILED -- last 80 lines:'
	tail -80 fix_build.log
	exit 1
fi
echo "fix kernel build ok ($(wc -l < fix_build.log) lines)"

rsh 'cd /usr/src && make installkernel KERNCONF=X86_64_GENERIC' \
	> fix_installkernel.log 2>&1
tail -2 fix_installkernel.log

rsh 'reboot' > /dev/null 2>&1 || true
sleep 15
i=0
while [ $i -lt 240 ]; do
	sleep 5
	if $ROOT/dfbsd-qemu/vm.sh status >/dev/null 2>&1; then break; fi
	i=$((i + 5))
done
sleep 5
rsh 'uname -a'
echo 'FIX BUILD OK'
