#!/bin/sh set -eu MNT=/mnt CONFIG_MNT=/mnt-config USB_DEV=/dev/sda EMMC_DEV=/dev/mmcblk0 EMMC_CONFIG_PART=/dev/mmcblk0p1 EMMC_ROOTFS_A_PART=/dev/mmcblk0p2 EMMC_ROOTFS_B_PART=/dev/mmcblk0p3 EMMC_DATA_PART=/dev/mmcblk0p4 DEFAULT_GLOB="${MNT}/${BUILD_TAG}_RELEASE_IMAGE" cleanup() { umount "$CONFIG_MNT" 2>/dev/null || true umount "$MNT" 2>/dev/null || true } log() { echo "[*] $*" } warn() { echo "[!] $*" >&2 } die() { echo "[!] ERROR: $*" >&2 exit 1 } reread_partitions() { log "Re-reading partition table..." blockdev --rereadpt "$EMMC_DEV" 2>/dev/null || true partprobe "$EMMC_DEV" 2>/dev/null || true partx -u "$EMMC_DEV" 2>/dev/null || true mdev -s 2>/dev/null || true } get_sectors() { devname="${1##*/}" cat "/sys/class/block/$devname/size" 2>/dev/null || echo 0 } wait_for_partition_ready() { part="$1" timeout="${2:-15}" i=0 while [ "$i" -lt "$timeout" ]; do if [ -b "$part" ]; then sectors="$(get_sectors "$part")" if [ "${sectors:-0}" -gt 0 ]; then log "Partition $part is present with $sectors sectors" return 0 fi fi i=$((i + 1)) sleep 1 done return 1 } mkdir -p "$MNT" "$CONFIG_MNT" trap cleanup EXIT log "Mounting USB..." mount "$USB_DEV" "$MNT" # Find a default image (first match) DEFAULT_IMG="$(ls $DEFAULT_GLOB 2>/dev/null | head -n1 || true)" echo if [ -n "$DEFAULT_IMG" ]; then echo "Default image found:" echo " $DEFAULT_IMG" else echo "No default image found under $DEFAULT_GLOB" fi echo printf "Image Location (%s): " "${DEFAULT_IMG:-/mnt/...}" read -r IMG if [ -z "$IMG" ]; then IMG="$DEFAULT_IMG" fi [ -n "$IMG" ] || die "No image selected" [ -f "$IMG" ] || die "Invalid image: $IMG" echo echo "Looking for env files on USB..." ENV_FILES="$(find "$MNT" -maxdepth 1 -type f -name '*.env' | sort || true)" if [ -n "$ENV_FILES" ]; then echo "Found env files:" echo "$ENV_FILES" | sed 's/^/ /' else echo "No *.env files found in $MNT" fi echo echo "About to write:" echo " Image: $IMG" echo " Target: $EMMC_DEV" echo printf "Type 'YES' to continue: " read -r CONFIRM [ "$CONFIRM" = "YES" ] || die "Aborted." log "Flashing image to eMMC..." gunzip -c "$IMG" > "$EMMC_DEV" log "Syncing flash write..." sync reread_partitions log "Waiting for partition nodes..." if ! wait_for_partition_ready "$EMMC_CONFIG_PART" 15; then warn "Initial partition scan did not settle; retrying after another reread..." reread_partitions sleep 2 wait_for_partition_ready "$EMMC_CONFIG_PART" 15 || die "config partition not ready: $EMMC_CONFIG_PART" fi # These are useful sanity checks, but not strictly required for copying config. wait_for_partition_ready "$EMMC_ROOTFS_A_PART" 5 || warn "rootfsA partition not ready yet: $EMMC_ROOTFS_A_PART" wait_for_partition_ready "$EMMC_ROOTFS_B_PART" 5 || warn "rootfsB partition not ready yet: $EMMC_ROOTFS_B_PART" wait_for_partition_ready "$EMMC_DATA_PART" 5 || warn "data partition not ready yet: $EMMC_DATA_PART" log "Partition sizes:" echo " $(basename "$EMMC_DEV"): $(get_sectors "$EMMC_DEV") sectors" echo " $(basename "$EMMC_CONFIG_PART"): $(get_sectors "$EMMC_CONFIG_PART") sectors" echo " $(basename "$EMMC_ROOTFS_A_PART"): $(get_sectors "$EMMC_ROOTFS_A_PART") sectors" echo " $(basename "$EMMC_ROOTFS_B_PART"): $(get_sectors "$EMMC_ROOTFS_B_PART") sectors" echo " $(basename "$EMMC_DATA_PART"): $(get_sectors "$EMMC_DATA_PART") sectors" if [ -n "$ENV_FILES" ]; then log "Mounting flashed config partition..." mount -t vfat "$EMMC_CONFIG_PART" "$CONFIG_MNT" || { warn "Mount failed; retrying once after partition reread..." reread_partitions sleep 2 mount -t vfat "$EMMC_CONFIG_PART" "$CONFIG_MNT" } log "Copying env files to config partition..." for f in $ENV_FILES; do base="$(basename "$f")" cp "$f" "$CONFIG_MNT/$base" echo " copied: $base" done log "Syncing copied config..." sync umount "$CONFIG_MNT" fi log "Done." log "Rebooting..." reboot -f