#!/bin/bash # push_firmware script # # Flashes firmware file to AVM devices or Speedport. # # Copyright (c) 2007 Michael Hampicke (mike@mhampicke.de) # 2007 Alexander Kriegisch (kriegaex, ip-phone-forum.de) # 2011 extended for ALICE 7570 by MaxMuster # 2019 extended by ram-boot and dual-boot modes for freetz-ng # 2020 extended by uimg support (uses fesc2000's uimg tool) # # Cygwin users note: # 1. There is NO guarantee whatsoever that this will work on Cygwin, even # though it does on my box (kriegaex). Provided as is. # 2. For FTP you need the 'ncftp' cygwin package (category 'net'). # 3. You need the 'ping' command from Windows (tested on XP), NOT from the # 'ping' cygwin package (please uninstall or change path so Windows # version is found first), because the cygwin version has no timeout # parameter as of today (2007-07-11). # 4. For 'hexdump' you need the 'util-linux' cygwin package (category # 'utils'). # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA UIMG_TOOL="${0%/*}/uimg" TSUM_TOOL="${0%/*}/tichksum" function wait_loader() { echo -en " * No reply from box, assuming switch-off or restart. Trying to re-detect box.\n Waiting " [ -z "$SLEEP1" ] && SLEEP1=do || sleep 1 while ! ping $ping_params $ip > /dev/null; do echo -n "." sleep 0.2 done echo -e ". found!\n" } function read_enval() { ftp -v -n < /dev/null; do echo -n "." sleep 0.2 done echo if [ $ISRAM ]; then if [ "${FULLSIZE//0/}" == "x" ]; then wait_loader enval="$(read_enval memsize)" [ "$enval" != "${enval#0x}" ] && FULLSIZE="$enval" [ -z "$FULLSIZE" ] && echo "Invalid value for memsize." && exit 1 echo " * Detected memsize: '$enval'" echo fi MAPSTART=0x80000000 # start mapped memory MAPLIMIT="0x$(printf '%.8x' $(( $MAPSTART + $FULLSIZE )))" FILESIZE="0x$(printf '%.8x' $(stat --printf='%s' "$mtdram1"))" FREESIZE="0x$(printf '%.8x' $(( $FULLSIZE - $FILESIZE )))" MTDSTART="0x$(printf '%.8x' $(( $MAPSTART + $FULLSIZE - $FILESIZE )))" echo -e " * MAPSTART=$MAPSTART" echo -e " * FULLSIZE=$FULLSIZE\t ($(($FULLSIZE/1024/1024)) MB)" echo -e " * MAPLIMIT=$MAPLIMIT" echo -e " * FILESIZE=$FILESIZE\t (~$(($FILESIZE/1024/1024)) MB)" echo -e " * FREESIZE=$FREESIZE\t (~$(($FREESIZE/1024/1024)) MB)" echo -e " * MTDSTART=$MTDSTART" echo -e fi if [ ! $ISSINGLE ]; then if [ ! $LFS ] || [ -n "$ISDUAL$ISUIMG" -a "$LFS" == "9" ]; then wait_loader enval="$(read_enval linux_fs_start)" [ "$enval" != "0" -a "$enval" != "1" -a "$enval" != "" ] && echo "Invalid value for linux_fs_start." && exit 1 echo " * Detected linux_fs_start: '${enval:-}'" [ -z "$enval" ] && enval=0 #factory [ -z "$LFS" ] && LFS="$(( ($enval + 1) % 2))" #other [ "$LFS" == "9" ] && LFS="$enval" #current echo " * Designated linux_fs_start: $LFS" echo fi if [ $ISRAM ]; then [ "$LFS" == "9" ] && LFS= elif [ $ISDUAL ]; then [ $LFS -ne 1 ] && ARMsysMTD='0' && ARMkrnMTD='1' && X86sysMTD='6' && X86krnMTD='7' [ $LFS -eq 1 ] && ARMsysMTD='11' && ARMkrnMTD='12' && X86sysMTD='13' && X86krnMTD='14' elif [ $ISUIMG ]; then [ $LFS -ne 1 ] && ARMsysMTD='6' && ARMkrnMTD='7' && X86sysMTD='0' && X86krnMTD='1' && ALLgwtMTD='TODO' [ $LFS -eq 1 ] && ARMsysMTD='=' && ARMkrnMTD='>' && X86sysMTD=';' && X86krnMTD='<' && ALLgwtMTD='TODO' [ -e $ALLgwt ] && echo " * GWFS (tar) mtd: $ALLgwtMTD" fi if [ -n "$ISDUAL$ISUIMG" ]; then echo " * Arm-System mtd: $ARMsysMTD" echo " * Arm-Kernel mtd: $ARMkrnMTD" echo " * x86-System mtd: $X86sysMTD" echo " * x86-Kernel mtd: $X86krnMTD" echo fi fi wait_loader echo " * Box is back up again, initiating transfer." echo if [ $ISSINGLE ]; then if [ $ISALICE ]; then basename=$(basename $0) echo "$basename: Trying to flash an image to an \"Alice\" 7570 FritzBox." [ $(which telnet) ] || { echo "$basename: Error finding required binary \"telnet\"." ; exit 1 ;} VALUES="$(telnet_hn | telnet 2>/dev/null| grep -e '^mtd[1\|5]\|^HWRevision')" || { echo "$basename: Error trying to get values from \"Alice\" FritzBox."; exit 1; } HWR=$(echo "$VALUES" | sed -n '/^HWRev/ s/HWRevision[^0-9]*//p') [ "153" = "$HWR" ] || { echo "$basename: Error veryfing HWRevision=153 as required for \"Alice\" FritzBox. Found: HWRevision=$HWR." ; exit 1 ;} MTD=$(echo "$VALUES" | sed -n '/^mtd/ s/mtd.[^0]*// p') $(echo $MTD | tr -d '\n' | grep '0x90040000,0x907E0000' | grep -q '0x907E0000,0x90F80000') || \ { echo -e "$basename: Error veryfing mtd values for \"Alice\" box. Found values:\n$MTD" ; exit 1 ;} size=$(stat -c %s $img) let max_size=7808*1024 if [ $size -ge $max_size ]; then kernel_mtd1=$(mktemp -t freetz_mtd1_XXX) || { echo "$basename: Error creating temporary file for mtd1."; exit 1; } kernel_mtd5=$(mktemp -t freetz_mtd5_XXX) || { echo "$basename: Error creating temporary file for mtd5."; exit 1; } dd if=${file} of=${kernel_mtd1} bs=1k count=7808 >/dev/null 2>&1 || { echo "$basename: Error creating image part for mtd1."; exit 1; } dd if=${file} of=${kernel_mtd5} bs=1k skip=7808 >/dev/null 2>&1 || { echo "$basename: Error creating image part for mtd5."; exit 1; } else ISALICE=false kernel_mtd1=$img fi else kernel_mtd1=$img fi fi if [ $FOUND_NCFTP ]; then if [ $ISRAM ]; then ncftpput \ -C -d stdout -u adam2 -p adam2 \ -o doNotGetStartCWD=1,useFEAT=0,useHELP_SITE=0,useCLNT=0,useSIZE=0,useMDTM=0 \ -W "quote MEDIA SDRAM" \ -W "quote SETENV memsize ${FREESIZE}" \ -W "quote SETENV kernel_args_tmp mtdram1=${MTDSTART},${MAPLIMIT}" \ -X "$([ ! $LFS ] && echo "quote SYST" || echo "quote SETENV linux_fs_start $LFS")" \ -Y "quote QUIT" \ $ip ${mtdram1} "${MTDSTART} ${MAPLIMIT}" || exit $? elif [ -n "$ISDUAL$ISUIMG" ]; then [ -e $ALLgwt ] && ncftpput \ -C -d stdout -u adam2 -p adam2 \ -o doNotGetStartCWD=1,useFEAT=0,useHELP_SITE=0,useCLNT=0,useSIZE=0,useMDTM=0 \ -W "quote MEDIA FLSH" \ $ip $ALLgwt mtd$ALLgwtMTD || exit $? ncftpput \ -C -d stdout -u adam2 -p adam2 \ -o doNotGetStartCWD=1,useFEAT=0,useHELP_SITE=0,useCLNT=0,useSIZE=0,useMDTM=0 \ -W "quote MEDIA FLSH" \ $ip $ARMsys mtd$ARMsysMTD || exit $? ncftpput \ -C -d stdout -u adam2 -p adam2 \ -o doNotGetStartCWD=1,useFEAT=0,useHELP_SITE=0,useCLNT=0,useSIZE=0,useMDTM=0 \ -W "quote MEDIA FLSH" \ $ip $ARMkrn mtd$ARMkrnMTD || exit $? ncftpput \ -C -d stdout -u adam2 -p adam2 \ -o doNotGetStartCWD=1,useFEAT=0,useHELP_SITE=0,useCLNT=0,useSIZE=0,useMDTM=0 \ -W "quote MEDIA FLSH" \ $ip $X86sys mtd$X86sysMTD || exit $? ncftpput \ -C -d stdout -u adam2 -p adam2 \ -o doNotGetStartCWD=1,useFEAT=0,useHELP_SITE=0,useCLNT=0,useSIZE=0,useMDTM=0 \ -W "quote MEDIA FLSH" \ -X "quote SETENV linux_fs_start $LFS" \ -Y "quote REBOOT" \ $ip $X86krn mtd$X86krnMTD || exit $? elif [ $ISSINGLE ]; then [ $ISALICE ] && ( ncftpput \ -C -d stdout -u adam2 -p adam2 \ -o doNotGetStartCWD=1,useFEAT=0,useHELP_SITE=0,useCLNT=0,useSIZE=0,useMDTM=0 \ -W "quote MEDIA FLSH" \ $ip ${kernel_mtd5} mtd5 || exit $? ) ncftpput \ -C -d stdout -u adam2 -p adam2 \ -o doNotGetStartCWD=1,useFEAT=0,useHELP_SITE=0,useCLNT=0,useSIZE=0,useMDTM=0 \ -W "quote MEDIA FLSH" \ -Y "quote REBOOT" \ $ip ${kernel_mtd1} mtd1 || exit $? else echo "miserable failure" && exit 1 fi elif [ $FOUND_FTP ]; then if [ $ISRAM ]; then ftp -n -p </dev/null 2>&1; then if [ -s "$tmpdir/var/tmp/kernel.image" -a -s "$tmpdir/var/tmp/filesystem.image" ]; then for f in "$tmpdir/var/tmp/kernel.image" "$tmpdir/var/tmp/filesystem.image"; do $TSUM_TOOL -r "$f" >/dev/null dd if="$f" bs=256 conv=sync 2>/dev/null done > "$mtdram1" fi fi if [ ! -s "$mtdram1" ]; then echo -e "\nError: file is not a valid ram-boot image to be written to the device.\n" >&2 exit 1 fi elif [ $ISDUAL ]; then tmpdir=$(mktemp -td freetz_XXX) || { echo "Error creating temporary directory."; exit 1; } ARMsys="$tmpdir/ARM-system.image" ARMkrn="$tmpdir/ARM-kernel.image" X86sys="$tmpdir/X86-system.image" X86krn="$tmpdir/X86-kernel.image" if tar -C $tmpdir/ -xf $file --wildcards '*.image' >/dev/null 2>&1; then mv "$tmpdir/var/remote/var/tmp/filesystem.image" "$ARMsys" 2>/dev/null mv "$tmpdir/var/remote/var/tmp/kernel.image" "$ARMkrn" 2>/dev/null mv "$tmpdir/var/remote/var/tmp/x86/filesystem.image" "$X86sys" 2>/dev/null mv "$tmpdir/var/remote/var/tmp/x86/kernel.image" "$X86krn" 2>/dev/null fi if [ ! -s "$ARMsys" -o ! -s "$ARMkrn" -o ! -s "$X86sys" -o ! -s "$X86krn" ]; then echo -e "\nError: file is not a valid dual-boot image to be written to the device.\n" >&2 exit 1 fi elif [ $ISUIMG ]; then tmpdir=$(mktemp -td freetz_XXX) || { echo "Error creating temporary directory."; exit 1; } ARMsys="$tmpdir/ARM-system.image" ARMkrn="$tmpdir/ARM-kernel.image" X86sys="$tmpdir/X86-system.image" X86krn="$tmpdir/X86-kernel.image" ALLgwt="$tmpdir/ALL-gw_fs.image" if tar -C $tmpdir/ -xf $file ./var/firmware-update.uimg >/dev/null 2>&1; then $UIMG_TOOL -u "$tmpdir/var/firmware-update.uimg" >/dev/null chmod +w $tmpdir/var/*.bin mv $tmpdir/var/*_ARM_ROOTFS.bin "$ARMsys" 2>/dev/null mv $tmpdir/var/*_ARM_KERNEL.bin "$ARMkrn" 2>/dev/null mv $tmpdir/var/*_ATOM_ROOTFS.bin "$X86sys" 2>/dev/null mv $tmpdir/var/*_ATOM_KERNEL.bin "$X86krn" 2>/dev/null # mv $tmpdir/var/*_GWFS.bin "$ALLgwt" 2>/dev/null # TODO fi if [ ! -s "$ARMsys" -o ! -s "$ARMkrn" -o ! -s "$X86sys" -o ! -s "$X86krn" ]; then echo -e "\nError: file is not a valid uimg-boot image to be written to the device.\n" >&2 exit 1 fi elif [ $ISSINGLE ]; then work=$file img="" while [ -z "$img" ]; do [ "$(uname -s)" == "Darwin" ] && CHECK="81 12 ed fe" || CHECK="1281 feed" hexdump -n4 "$work" | grep -iq "$CHECK" && img="$work" if [ -z "$img" ]; then if tar tf "$work" ./var/tmp/kernel.image >/dev/null 2>&1; then tmpimg=$(mktemp -t freetz_XXX) || { echo "Error creating temporary file."; exit 1; } tar -Oxf "$work" ./var/tmp/kernel.image > $tmpimg work=$tmpimg else echo -e "\nError: file is not a valid single-boot image to be written to the device.\n" >&2 exit 1 fi fi done else echo "miserable failure" && exit 1 fi } function cleanup() { local val=$? [ -n "$tmpdir" -a -d "$tmpdir" ] && rm -rf "$tmpdir"; [ -n "$tmpimg" -a -f "$tmpimg" ] && rm -rf "$tmpimg"; [ -n "${kernel_mtd1}" -a -f "${kernel_mtd1}" ] && rm -rf "${kernel_mtd1}"; [ -n "${kernel_mtd5}" -a -f "${kernel_mtd5}" ] && rm -rf "${kernel_mtd5}"; exit $val } trap cleanup EXIT SIGTERM SIGINT usage() { echo echo "Usage: $0 [image] [ -m ] [ -f ] [ -ip ] [ -ram ] [ -lfs <0|1|9> ] [ -cmd ] [ -hn ]" echo echo "[image] When no 'image' file is given, images/latest.image will be tried." echo "-ms Force mode single-boot (classic devices, like 7270 & 7390)" echo "-mr Force mode ram-boot (newer devices, like 7490 & 7590)" echo "-md Force mode dual-boot (classic docsis devices, like 6490 & 6590)" echo "-mu Force mode uimg-boot (newer docsis devices, like 6591 & 6660)" echo " See https://bitbucket.org/fesc2000/ffritz/src/6591/README-6591.md" echo "-mf Force mode fit-boot (newer AX devices, like 7530 AX)" echo " Not supported yet!" echo "-f Disable safety prompt." echo "-ip Bootloader IP address or hostname, default 192.168.178.1" echo "-ram Only ram-boot mode: Usable ram size in MB of your device." echo " Without this parameter, the default of 128 MB will be used." echo " Some devices like Repeater 3000 need 256 MB to flash." echo " Use '0' to detect and use all available ram." echo "-lfs <0|1|9> Not single-boot mode: Set linux_fs_start to 0 or 1 and flash into this." echo " Without this parameter, the inactive linux_fs_start will be used." echo " Use '9' for the currently active linux_fs_start." echo "-cmd Force the prefered usage of ftp or ncftp command for upload." echo "-hn Only single-boot mode: Flash to an 'Alice/HanseNet' version of 7570." echo exit 1 } while [ $# -ge 1 ]; do case "$1" in (-ms|-msingle) ISSINGLE=true ;; (-mr|-mram) ISRAM=true ;; (-md|-mdual) ISDUAL=true ;; (-mu|-muimg) ISUIMG=true ;; (-mf|-mfit) ISFIT=true ;; (-f|-force) ISFORCE=true ;; (-ip) [ -z "$2" -o "$2" != "${2#\-}" ] && usage ip=$2 shift ;; (-ram) [ -z "$2" -o "$2" != "${2#\-}" ] && usage [ "$2" -ge 0 2>/dev/null ] && FULLSIZE="0x$(printf '%.8x' "$(( $2 * 1048576 ))")" [ -z "$FULLSIZE" ] && echo "Invalid value for ram size" && usage shift ;; (-lfs) [ "$2" != "0" -a "$2" != "1" -a "$2" != "9" ] && echo "Invalid linux_fs_start value" && usage LFS=$2 shift ;; (-cmd) [ "$2" != "ftp" -a "$2" != "ncftp" ] && echo "Invalid command value" && usage CMD=$2 shift ;; (-hn) ISALICE=true ;; (-h|--help) usage ;; (*) if [ -z "$file" -a "$1" == "${1#\-}" ]; then file="$1" else echo "Unknown parameter: $1" && usage fi ;; esac shift done # environment [ "$FREETZ_FORCEPF" == "true" ] && ISFORCE=true # file checks [ -z "$file" ] && [ -e images/latest.image ] && file="images/latest.image" [ -L "$file" ] && file="$(realpath "$file")" && file=${file#$PWD/} [ -z "$file" ] && usage [ -n "$file" ] || { echo "An image file is mandatory." ; exit 1; } [ -e "$file" ] || { echo "No such file or directory: $file" ; exit 1; } [ -f "$file" ] || { echo "Not a file: $file" ; exit 1; } [ -r "$file" ] || { echo "Access denied: $file" ; exit 1; } # img detect if [ -z "$ISSINGLE$ISDUAL$ISRAM$ISUIMG$ISFIT" ]; then echo -e "\n * Analyzing '$file' ... " if tar tf "$file" --wildcards '*/fit-image' &>/dev/null; then ISFIT=true elif tar tf "$file" --wildcards '*/firmware-update.uimg' &>/dev/null; then ISUIMG=true elif dd if="$file" bs=1 skip=2 count=2 2>/dev/null | base64 | grep -q '^7f4=$'; then INMEM=true ISRAM=true else N="$(tar tf "$file" --wildcards '*/kernel.image' 2>/dev/null | wc -l)" S="$(tar -Oxf "$file" ./var/tmp/filesystem.image 2>/dev/null | wc -c)" [ "$N" == "1" -a "$S" != "0" ] && ISRAM=true [ "$N" == "2" -a "$S" == "0" ] && ISDUAL=true [ "$N" == "1" -a "$S" == "0" ] && ISSINGLE=true fi fi [ -z "$ISSINGLE$ISDUAL$ISRAM$ISUIMG$ISFIT" ] && echo "Can not recognize image, please use '-m'." && exit 1 # arg check [ ! $ISSINGLE ] && [ $ISALICE ] && echo "Parameter '-hn' is only allowed for single-boot mode." && exit 1 [ $ISSINGLE ] && [ $LFS ] && echo "Parameter '-lfs' is not allowed for single-boot mode." && exit 1 [ $ISDUAL ] && [ ! $LFS ] && LFS="1" [ $ISUIMG ] && [ ! $LFS ] && LFS="1" [ $ISUIMG ] && [ ! -x $UIMG_TOOL ] && echo "File $UIMG_TOOL missing. Run 'make uimg' first." && exit 1 [ $ISRAM ] && [ ! -x $TSUM_TOOL ] && echo "File $TSUM_TOOL missing. Run 'make tichksum-host' first." && exit 1 [ ! $ISRAM ] && [ $FULLSIZE ] && echo "Parameter '-ram' is only allowed for ram-boot mode." && exit 1 [ $ISFIT ] && echo "FIT is not supported yet!" && exit 1 prepare_image # IPs [ ! $ip ] && ip=192.168.178.1 oa="unknown" for horst in $(hostname -I); do [ ${horst%.*} == ${ip%.*} ] && oa=$horst done if [ "$oa" == "unknown" ]; then echo -ne "\n * Warning: It seems your network is not able to reach\n $ip directly." case $(ls /sys/class/net/ | grep -v "^lo$" | wc -w) in 0) echo ;; 1) echo " This command could help to fix:" ;; *) echo " One(!) of these commands could help to fix:" ;; esac for x in $(ls /sys/class/net/ | grep -v "^lo$" ); do echo -e " $ \033[4msudo ifconfig $x:0 ${ip%.*}.$(ifconfig $x | sed -rn 's/.*inet [0-9\.]*\.([0-9]*) .*/\1/p') up\033[0m" done echo -n " Proceed anyway? ([y]/n) " read -n 1 -s PROCEED_NETCFG [ "$PROCEED_NETCFG" != "y" -a -n "$PROCEED_NETCFG" ] && echo -e "n\n\naborted\n" && exit echo "$PROCEED_NETCFG" fi ping_params="-c1 -w1" if [ "$(uname -s)" == "Darwin" ]; then ping_params="-c1 -t1" elif [ "$(uname -o)" == "Cygwin" ]; then CYGWIN=1 ping_params="-n 1 -w 500" fi [ -x "$(which ncftpput 2>/dev/null)" ] && FOUND_NCFTP=true [ "$(uname -s)" == "Linux" -a -x "$(which ftp 2>/dev/null)" ] && FOUND_FTP=true if [ -z "$FOUND_NCFTP" -a -z "$FOUND_FTP" ]; then echo "You have to install 'ncftp' or 'ftp' in order to use this script." exit 1 fi if [ -z "$FOUND_FTP" ]; then [ $ISRAM ] && [ "${FULLSIZE//0/}" == "x" ] && echo "Parameter '-ram' has to be bigger than 0 if you have no 'ftp' installed." && exit 1 [ ! $ISSINGLE ] && [ -z "$LFS" ] && echo "Parameter '-lfs' is mandatory if you have no 'ftp' installed." && exit 1 [ $ISDUAL ] && [ "$LFS" == "9" ] && echo "Parameter '-lfs' with 0 or 1 is mandatory if you have no 'ftp' installed." && exit 1 [ $ISUIMG ] && [ "$LFS" == "9" ] && echo "Parameter '-lfs' with 0 or 1 is mandatory if you have no 'ftp' installed." && exit 1 fi if [ -n "$CMD" ]; then [ "$CMD" == "ftp" ] && FOUND_NCFTP="" [ "$CMD" == "ncftp" ] && FOUND_FTP="" fi if [ -n "$FOUND_NCFTP" -a -n "$FOUND_FTP" ]; then [ $ISRAM ] && FOUND_NCFTP="" [ $ISDUAL ] && FOUND_NCFTP="" [ $ISUIMG ] && FOUND_NCFTP="" [ $ISSINGLE ] && FOUND_FTP="" [ $ISALICE ] && FOUND_NCFTP="" fi [ -n "$FOUND_NCFTP" ] && UCMD="ncftpput" || UCMD="ftp" # logging echo echo " * Using command: $UCMD" echo " * Target host: $ip" echo " * Outgoing IP: $oa" if [ $ISUIMG ]; then OUTVAL="uimg" elif [ $ISDUAL ]; then OUTVAL="dual" elif [ $INMEM ]; then OUTVAL="inmemory" elif [ $ISRAM ]; then OUTVAL="ram" else OUTVAL="single" fi echo " * Flash mode: $OUTVAL-boot" if [ $ISRAM ]; then [ -z "$FULLSIZE" ] && FULLSIZE="0x08000000" [ "${FULLSIZE//0/}" == "x" ] && OUTVAL="" || OUTVAL="$(( $FULLSIZE /1024/1024 )) MB" echo " * Allowed memory size: $OUTVAL" fi if [ ! $ISSINGLE ]; then [ -n "$LFS" ] && OUTVAL="$LFS" [ -z "$LFS" ] && OUTVAL="" [ "$LFS" == "9" ] && OUTVAL="" echo " * Designated linux_fs_start: $OUTVAL" fi # if [ $ISFORCE ]; then echo -e " * File: \033[4m$file\033[0m" push_fw else echo echo " !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!!" echo " !!! THERE IS NO WARRANTY AT ALL !!! USE AT YOUR OWN RISK !!!" echo echo " * Are you sure, that you want to flash this file to the device?" echo -e " \033[4m$file\033[0m" echo -n " Proceed? (y/[n]) " read -n 1 -s PROCEED [ "$PROCEED" != "y" ] && echo -e "n\n\naborted\n" && exit echo "$PROCEED" push_fw fi echo echo done exit 0