#!/usr/bin/env bash # M1 check: compare our image with the kernel's own disk.img, file by file. # Both are GPT + FAT32; mtools reads the partition at byte offset 1 MiB # (`-i image@@1M`), so nothing is mounted. # # Prints: the /bin program lists side by side (must be equal), the other # files (must be equal, byte for byte), and for each program whether the # bytes are identical. Rust programs built by Cargo are expected to differ # in bytes from the kernel's single-file rustc builds (Cargo adds crate # metadata), so only list equality and non-program files fail the check. # # Since M2 our image has more than the kernel's: Foundry OS's own programs # (env FOUNDRY_BIN, left out of the list comparison), files of its own # outside /bin (env FOUNDRY_FILES, paths relative to the image root, left # out) and a "Foundry OS" block in scripts/selftest.sh (cut out before # comparing that file). # # Usage: [FOUNDRY_BIN="prog ..."] [FOUNDRY_FILES="path ..."] scripts/compare-image.sh OURS KERNELS OUT_DIR set -euo pipefail fail=0 OURS=$1 THEIRS=$2 OUT=$(realpath -m "$3")/compare export MTOOLS_SKIP_CHECK=1 rm -rf "$OUT" && mkdir -p "$OUT/ours" "$OUT/kernel" mcopy -s -n -i "$OURS@@1M" '::/*' "$OUT/ours/" mcopy -s -n -i "$THEIRS@@1M" '::/*' "$OUT/kernel/" (cd "$OUT/ours/bin" && ls | LC_ALL=C sort) > "$OUT/bin-ours-all.txt" grep -vxF -f <(printf '%s\n' ${FOUNDRY_BIN:-} '') "$OUT/bin-ours-all.txt" > "$OUT/bin-ours.txt" || true echo "== Foundry OS's own programs (not in the kernel's image): ${FOUNDRY_BIN:-none}" for p in ${FOUNDRY_BIN:-}; do [ -f "$OUT/ours/bin/$p" ] || { echo " MISSING /bin/$p"; fail=1; }; done for f in ${FOUNDRY_FILES:-}; do if [ -f "$OUT/ours/$f" ]; then echo " Foundry OS file: $f (not compared)"; rm "$OUT/ours/$f" else echo " MISSING $f"; fail=1; fi done # Our selftest.sh = the kernel's + a "Foundry OS" block; compare without it. sed -i '/^# ---- Foundry OS ----$/,/^# ---- end Foundry OS ----$/d' "$OUT/ours/scripts/selftest.sh" (cd "$OUT/kernel/bin" && ls | LC_ALL=C sort) > "$OUT/bin-kernel.txt" echo "== /bin program list: ours $(wc -l < "$OUT/bin-ours.txt"), kernel $(wc -l < "$OUT/bin-kernel.txt")" if diff -u "$OUT/bin-kernel.txt" "$OUT/bin-ours.txt"; then echo " same list" else echo " LISTS DIFFER (- kernel, + ours)"; fail=1 fi echo "== files outside /bin (must be byte-identical)" (cd "$OUT/ours" && find . -path ./bin -prune -o -type f -print | LC_ALL=C sort) > "$OUT/files-ours.txt" (cd "$OUT/kernel" && find . -path ./bin -prune -o -type f -print | LC_ALL=C sort) > "$OUT/files-kernel.txt" if ! diff -u "$OUT/files-kernel.txt" "$OUT/files-ours.txt"; then fail=1; fi while read -r f; do if [ -f "$OUT/kernel/$f" ] && cmp -s "$OUT/ours/$f" "$OUT/kernel/$f"; then echo " same $f" else echo " DIFFERENT $f"; fail=1; fi done < "$OUT/files-ours.txt" echo "== /bin bytes (Rust programs from rust/ may differ: Cargo vs plain rustc)" same=0 diff=0 while read -r p; do [ -f "$OUT/kernel/bin/$p" ] || continue a=$(stat -c %s "$OUT/kernel/bin/$p") b=$(stat -c %s "$OUT/ours/bin/$p") if cmp -s "$OUT/kernel/bin/$p" "$OUT/ours/bin/$p"; then printf ' same %-12s %8d bytes\n' "$p" "$a"; same=$((same + 1)) else printf ' different %-12s %8d -> %8d bytes\n' "$p" "$a" "$b"; diff=$((diff + 1)) fi done < "$OUT/bin-ours.txt" echo "== $same identical, $diff different in bytes; extracted trees in $OUT" [ $fail = 0 ] && echo "[compare] OK: same program list and same non-program files" || { echo "[compare] FAILED"; exit 1; }