#!/bin/sh
# Verify an AM335x/BeagleBone-bootable SD image OR a raw card against the boot
# ROM's documented requirements.
# See /work/bbb/upstream/03-am335x-sd-layout-requirements.md
#
# Governing rule: the MBR partition entry's sector count must EQUAL the FAT
# filesystem's own sector count. If they disagree the boot ROM silently rejects
# the card and emits no console output at all.
#
# NOTE: reads are sector-aligned (bs=512) because FreeBSD raw disk devices
# reject unaligned/bs=1 reads. Sectors are staged to a temp file and parsed
# from there, so the same code works for files and devices.
set -eu

IMG=${1:?usage: verify-image.sh <image-or-device>}
TMP=$(mktemp -t verifyimg) || exit 1
trap 'rm -f "$TMP"' EXIT
fail=0

# sector <lba> -> stage that 512-byte sector into $TMP
sector() {
    dd if="$IMG" bs=512 skip="$1" count=1 of="$TMP" 2>/dev/null || return 1
    [ -s "$TMP" ] || return 1
}
b()    { dd if="$TMP" bs=1 skip="$1" count=1 2>/dev/null | hexdump -e '1/1 "%02x"'; }
le16() { dd if="$TMP" bs=1 skip="$1" count=2 2>/dev/null | hexdump -e '1/2 "%u"'; }
le32() { dd if="$TMP" bs=1 skip="$1" count=4 2>/dev/null | hexdump -e '1/4 "%u"'; }

check() {
    if [ -z "$2" ]; then
        printf 'FAIL  %-42s NO DATA (media absent?)\n' "$1"; fail=1; return
    fi
    if [ "$2" = "$3" ]; then
        printf 'ok    %-42s %s\n' "$1" "$2"
    else
        printf 'FAIL  %-42s got %s, want %s\n' "$1" "$2" "$3"; fail=1
    fi
}

if ! sector 0; then
    echo "FAIL  cannot read sector 0 of $IMG (media absent or unreadable)"
    exit 1
fi

sig="$(b 510)$(b 511)"
check "MBR signature @0x1FE" "$sig" "55aa"

p1flag=$(b 446); p1type=$(b 450); p1start=$(le32 454); p1size=$(le32 458)
check "partition 1 active flag" "$p1flag" "80"
case "$p1type" in
    0c|0e|06) printf 'ok    %-42s 0x%s\n' "partition 1 type (FAT)" "$p1type" ;;
    "")       printf 'FAIL  %-42s NO DATA\n' "partition 1 type"; fail=1 ;;
    *)        printf 'FAIL  %-42s 0x%s, want 0x0c/0x0e/0x06\n' "partition 1 type" "$p1type"; fail=1 ;;
esac
printf 'info  %-42s %s\n' "partition 1 start LBA" "${p1start:-none}"

if [ -z "$p1start" ] || [ "$p1start" = 0 ]; then
    echo "FAIL  partition 1 has no valid start LBA"; exit 1
fi

if ! sector "$p1start"; then
    echo "FAIL  cannot read FAT boot sector at LBA $p1start"; exit 1
fi

bps=$(le16 11); spc=$(b 13); tot16=$(le16 19); tot32=$(le32 32)
check "BPB BytesPerSector" "$bps" "512"        # ROM tests this explicitly
printf 'info  %-42s 0x%s\n' "BPB SectorsPerCluster" "${spc:-??}"

if [ -n "$tot16" ] && [ "$tot16" -ne 0 ] 2>/dev/null; then fstot=$tot16; else fstot=$tot32; fi
printf 'info  %-42s %s\n' "FAT filesystem sectors" "${fstot:-none}"

check "MBR p1 size == FAT sector count" "${p1size:-}" "${fstot:-}"

echo
if [ "$fail" -ne 0 ]; then
    echo "WILL NOT BOOT: one or more documented ROM requirements violated."
    exit 1
fi
echo "All documented boot ROM requirements satisfied."
