#!/bin/bash echo # 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) # 2021 extended by fitimg support # # 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 # workaround for eg debian PATH=${PATH:+${PATH}:}/sbin UIMG_TOOL="${0%/*}/uimg" TSUM_TOOL="${0%/*}/tichksum" FDTD_TOOL="${0%/*}/fit/fdtdump" 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 <<EOT | sed -rn "s/^$1[ \t]*//p" open $ip user adam2 adam2 quote GETENV $1 quote REBOOT quit EOT } function push_fw() { trap 'echo ; echo "aborted" ; exit 1' TERM INT if [ ! $ISWAITS ]; then echo echo " * You should now reboot your box ($ip). Waiting for shut down." echo " Switch off, if reboot is not detected because it happens too quickly." echo " Some newer bootloader versions allow to flash on power-cycle only." echo -n " " while ping $ping_params $ip > /dev/null; do echo -n "." sleep 0.2 done fi echo if [ -n "$ISRAM$ISFIT" ]; 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 [ $ISRAM ] && FILESIZE="$(stat --printf='%s' "$mtdram1")" [ $ISFIT ] && FILESIZE="$(stat --printf='%s' "$fitimage")" [ "$ALIBYTES" != "0" ] && ALIBYTES="$(( $ALIBYTES - ( $FILESIZE % $ALIBYTES ) ))" FILESIZE="0x$(printf '%.8x' $(( $FILESIZE )) )" ALIBYTES="0x$(printf '%.8x' $(( $ALIBYTES )) )" MAPSTART="0x$(printf '%.8x' $(( $MAPSTART )) )" MAPLIMIT="0x$(printf '%.8x' $(( $MAPSTART + $FULLSIZE )) )" FREESIZE="0x$(printf '%.8x' $(( $FULLSIZE - $FILESIZE - $ALIBYTES )) )" MTDSTART="0x$(printf '%.8x' $(( $MAPSTART + $FULLSIZE - $FILESIZE - $ALIBYTES )) )" 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 " * ALIBYTES=$ALIBYTES\t (~$(($ALIBYTES/1024 )) kB)" 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:-<unset>}'" [ -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 [ -n "$ISRAM$ISFIT" ]; 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." [ $(command -v 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 [ $ISFIT -a -n "$FITV" ]; 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 kernel_args \"\"" \ -W "quote SETENV kernel_args_tmp \"mtdram=rootfs_ram,${FITV/ /,}\"" \ -Y "quote QUIT" \ $ip ${fitimage} "${FITV}" || exit $? elif [ $ISFIT -a -z "$FITV" ]; 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 \"${AFU}mtdram1=${MTDSTART},${MAPLIMIT} mtdparts_ext=update-image.0:${FILESIZE}@0x0(fit-image)\"" \ -Y "quote QUIT" \ $ip ${fitimage} "${MTDSTART} ${MAPLIMIT}" || exit $? elif [ $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 [ $ISFIT -a -n "$FITV" ]; then ftp -n -p <<EOT open $ip user adam2 adam2 debug bin quote MEDIA SDRAM quote SETENV kernel_args \"\" quote SETENV kernel_args_tmp \"mtdram=rootfs_ram,${FITV/ /,}\" put ${fitimage} "${FITV}" quit EOT elif [ $ISFIT -a -z "$FITV" ]; then ftp -n -p <<EOT open $ip user adam2 adam2 debug bin quote MEDIA SDRAM quote SETENV memsize ${FREESIZE} quote SETENV kernel_args_tmp \"${AFU}mtdram1=${MTDSTART},${MAPLIMIT} mtdparts_ext=update-image.0:${FILESIZE}@0x0(fit-image)\" put ${fitimage} "${MTDSTART} ${MAPLIMIT}" quit EOT elif [ $ISRAM ]; then ftp -n -p <<EOT open $ip user adam2 adam2 debug bin quote MEDIA SDRAM quote SETENV memsize ${FREESIZE} quote SETENV kernel_args_tmp mtdram1=${MTDSTART},${MAPLIMIT} put ${mtdram1} "${MTDSTART} ${MAPLIMIT}" $([ $LFS ] && echo quote SETENV linux_fs_start $LFS) quit EOT elif [ -n "$ISDUAL$ISUIMG" ]; then ftp -n -p <<EOT open $ip user adam2 adam2 debug bin quote MEDIA FLSH put $ARMsys mtd$ARMsysMTD put $ARMkrn mtd$ARMkrnMTD put $X86sys mtd$X86sysMTD put $X86krn mtd$X86krnMTD $([ -e $ALLgwt ] && echo put $ALLgwt mtd$ALLgwtMTD) quote SETENV linux_fs_start $LFS quote REBOOT quit EOT elif [ $ISSINGLE ]; then ftp -n -p <<EOT open $ip user adam2 adam2 debug bin quote MEDIA FLSH put ${kernel_mtd1} mtd1 $([ $ISALICE ] && echo put ${kernel_mtd5} mtd5 ) quote REBOOT quit EOT else echo "miserable failure" && exit 1 fi fi } telnet_hn() { echo open $ip 21 sleep 0.2 echo USER adam2 sleep 0.2 echo PASS adam2 sleep 0.2 echo GETENV mtd1 sleep 0.2 echo GETENV mtd5 sleep 0.2 echo GETENV HWRevision sleep 0.2 echo QUIT sleep 0.2 } prepare_image() { if [ $ISFIT ]; then tmpdir=$(mktemp -td freetz_XXX) || { echo "Error creating temporary directory."; exit 1; } fitimage="$tmpdir/fitboot.flash" if tar -C $tmpdir/ -xf $file --wildcards '*/fit-image' >/dev/null 2>&1; then if [ -s "$tmpdir/var/tmp/fit-image" ]; then mv "$tmpdir/var/tmp/fit-image" "$fitimage" fi fi if [ ! -s "$fitimage" ]; then echo -e "Error: file is not a valid fit-boot image to be written to the device.\n" >&2 exit 1 fi # FITV="$(tail -c +73 "$fitimage" | $FDTD_TOOL - 2>/dev/null | sed -nr 's/.*"mtdram=/mtdram=/p')" FITV="$(strings "$fitimage" | grep 'mtdram=')" if echo "$FITV" | grep -q 'mtdram=ram-filesystem,'; then FITV='' elif echo "$FITV" | grep -q 'mtdram=rootfs_ram,'; then echo -e "Error: it is not known how to flash a fit-boot image with 'rootfs_ram' method yet." >&2 echo -e "Error: run a recovery.exe and get a capture by wireguard or tcpdump to add it." >&2 echo -e "Error: meanwhile install an older firmware and flash this one by the web interface.\n" >&2 read -rsn1 -t2 v [ "$v" != "v" ] && exit 1 FITV="$(echo "$FITV" | sed -rn 's/.*mtdram=rootfs_ram,([0-9A-Fa-fx]*),([0-9A-Fa-fx]*.*)/\1 \2/p')" else FITV='' fi elif [ $ISRAM ]; then tmpdir=$(mktemp -td freetz_XXX) || { echo "Error creating temporary directory."; exit 1; } mtdram1="$tmpdir/ramboot.flash" if [ $INMEM ]; then cp -p $file $mtdram1 elif tar -C $tmpdir/ -xf $file --wildcards '*.image' >/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 "Error: 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 "Error: 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 "Error: 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 "Error: 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() { cat << EOX Usage: $0 [image] [ -m<s|r|d|u|f> ] [ -f ] [ -w ] [ -ip <ip> ] [ -map <hex> ] [ -ali <kb> ] [ -ram <mb> ] [ -lfs <0|1|9> ] [ -cmd <ftp|ncftp> ] [ -hn ] [image] When no 'image' file is given, images/latest.image will be tried. -ms Force mode single-boot (classic devices, like 7270 & 7390) -mr Force mode ram-boot (newer devices, like 7490 & 7590) -md Force mode dual-boot (classic docsis devices, like 6490 & 6590) -mu Force mode uimg-boot (newer docsis devices, like 6591 & 6660) See https://bitbucket.org/fesc2000/ffritz/src/6591/README-6591.md -mf Force mode fit-boot (latest devices, like 5530 & 7530 AX) -f Disable safety prompt, force instant flash. -w The device is yet halted in the bootloader, don't wait for shutdown. -ip <ip> Bootloader IP address or hostname, default 192.168.178.1 -map <hex> Only ram-boot and fit-boot mode: Start of mapped memory (PHYS_OFFSET). -ali <kb> Only ram-boot and fit-boot mode: Alignment in kB of the uploaded file. Without this parameter, the default for fit-boot is 64 and ram-boot 0. -ram <mb> Only ram-boot and fit-boot mode: Usable ram size in MB of your device. Without this parameter, the default of 128 MB (FIT: 384) will be used. Some devices like Repeater 3000 need 256 MB to flash. Use '0' to detect and use all available ram. -lfs <0|1|9> Not single- and fit-boot mode: Set linux_fs_start to 0 or 1 and flash this. Without this parameter, the inactive linux_fs_start will be used. Use '9' for the currently active linux_fs_start. -afu Only fit-boot: No avm_fwupdate, run system from ram without flash it. -cmd <ftp|ncftp> Force the prefered usage of ncftp (buggy) or ftp command for upload. -hn Only single-boot mode: Flash to an 'Alice/HanseNet' version of 7570. If flashing ram-boot/nand/inmemory does not work... For ram-boot mode you may need to set a larger '-ram' value then the default of '128' MB. You could use '-ram 0' to detect the size and use the maximum. The value AVM uses is hardcoded into the recovery file and does not always use all available memory. A smaller value is okay as long as the image in the ram has enough ram to boot and flash itsef. EOX 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 ;; (-w|-waits) ISWAITS=true ;; (-ip) [ -z "$2" -o "$2" != "${2#\-}" ] && usage ip=$2 shift ;; (-map) MAPSTART="$2" [ "0x" != "${2:0:2}" ] && MAPSTART='' [ "x" != "$(echo $2 | sed 's/[0-9a-fA-F]//g')" ] && MAPSTART='' [ "$MAPSTART" == "0" -a "${MAPSTART//0/}" != "x" ] && MAPSTART='' [ -z "$MAPSTART" ] && echo "Invalid value for map start" && usage shift ;; (-ali) ALIBYTES="$2" [ -n "$ALIBYTES" -a -z "${ALIBYTES##0}" ] && ALIBYTES="0" [ "$ALIBYTES" != "0" ] && ALIBYTES="${ALIBYTES##0}" [ "$(( $ALIBYTES % 4 ))" != "0" ] && ALIBYTES='' || ALIBYTES="$(( $ALIBYTES * 1024 ))" [ -z "$ALIBYTES" ] && echo "Invalid value for alignment" && usage 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 ;; (-afu) NOAFU=true 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 [ "$FREETZ_WAITSPF" == "true" ] && ISWAITS=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 PRODUCT="$(tar -Oxf "$file" ./var/content 2>/dev/null | sed -n 's/^Product=//p')" if [ -z "$ISSINGLE$ISDUAL$ISRAM$ISUIMG$ISFIT" ]; then echo " * 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<s|r|d|u|f>'." && 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 [ ! $ISFIT ] && [ $NOAFU ] && echo "Parameter '-afu' is only allowed for fit-boot mode." && exit 1 [ $ISFIT ] && [ $LFS ] && echo "Parameter '-lfs' is not allowed for fit-boot mode." && exit 1 [ $ISFIT ] && [ ! $LFS ] && LFS="9" [ $ISDUAL ] && [ ! $LFS ] && LFS="1" [ $ISUIMG ] && [ ! $LFS ] && LFS="1" [ $ISUIMG ] && [ ! -x $UIMG_TOOL ] && echo "File $UIMG_TOOL missing. Run 'make uimg-host' first." && exit 1 [ $ISRAM ] && [ ! -x $TSUM_TOOL ] && echo "File $TSUM_TOOL missing. Run 'make tichksum-host' first." && exit 1 [ $ISFIT ] && [ ! -x $FDTD_TOOL ] && echo "File $FDTD_TOOL missing. Run 'make dtc-host' first." && exit 1 [ ! $ISRAM ] && [ ! $ISFIT ] && [ $FULLSIZE ] && echo "Parameter '-ram' is only allowed for ram-boot and fit-boot mode." && exit 1 [ ! $ISRAM ] && [ ! $ISFIT ] && [ $MAPSTART ] && echo "Parameter '-map' is only allowed for ram-boot and fit-boot mode." && exit 1 [ ! $ISRAM ] && [ ! $ISFIT ] && [ $ALIBYTES ] && echo "Parameter '-ali' is only allowed for ram-boot and fit-boot mode." && exit 1 prepare_image # IPs [ ! $ip ] && ip=192.168.178.1 oa="unknown" for horst in $(ip -4 -o addr show scope global up | grep -Po 'inet \K[\d.]+'); 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 "$(command -v ncftpput)" ] && FOUND_NCFTP=true [ "$(uname -s)" == "Linux" -a -x "$(command -v ftp)" ] && 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 [ -n "$ISRAM$ISFIT" ] && [ "${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 [ $ISFIT ] && FOUND_NCFTP="" [ $ISRAM ] && FOUND_NCFTP="" [ $ISDUAL ] && FOUND_NCFTP="" [ $ISUIMG ] && FOUND_NCFTP="" [ $ISSINGLE ] && FOUND_FTP="" [ $ISALICE ] && FOUND_NCFTP="" fi [ -n "$FOUND_NCFTP" ] && UCMD="ncftpput" || UCMD="ftp" # logging [ -n "$PRODUCT" ] && echo " * Product: $PRODUCT" echo " * Using command: $UCMD" echo " * Target host: $ip" echo " * Outgoing IP: $oa" if [ $ISUIMG ]; then OUTVAL="uimg" elif [ $ISFIT ]; then OUTVAL="fit" 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 [ -n "$ISUIMG" ]; then case "$PRODUCT" in Fritz_Box_HW267*) echo -e "\n\tThis device 6690 is not yet tested. Remove this warning only if you know what you are doing. Abort.\n"; exit 1 ;; esac fi if [ -n "$ISRAM$ISFIT" ]; then if [ -z "$MAPSTART" ]; then case "$PRODUCT" in # BCM Fritz_Box_HW224*) MAPSTART=0x00000000 ;; # 7581 Fritz_Box_HW228*) MAPSTART=0x00000000 ;; # 7582 # FIT Fritz_Box_HW253*) MAPSTART=0x40000000 ;; # 6000 Fritz_Box_HW256*) MAPSTART=0x00000000 ;; # 7539 Fritz_Box_HW257*) MAPSTART=0x20000000 ;; # 5530 Fritz_Box_HW261*) MAPSTART=0x40000000 ;; # 4060 Fritz_Box_HW268*) MAPSTART=0x40000000 ;; # 1209 # Fritz_Box_HW270*) MAPSTART=0x?0000000 ;; # 3009 Fritz_Box_HW271*) MAPSTART=0x40000000 ;; # 7510 Fritz_Box_HW272*) MAPSTART=0x40000000 ;; # 5590 *) [ $ISRAM ] && MAPSTART=0x80000000 [ $ISFIT ] && MAPSTART=0x40000000 ;; esac fi if [ -z "$FULLSIZE" ]; then case "$PRODUCT" in # RAM Fritz_Box_HW234*) FULLSIZE=0x0C000000 ;; # 6890 (192 MB) Fritz_Box_HW236*) FULLSIZE=0x10000000 ;; # 7530 (256 MB) Fritz_Box_HW223*) FULLSIZE=0x10000000 ;; # 5490 (256 MB) Fritz_Box_HW246*) FULLSIZE=0x10000000 ;; # 3000 (256 MB) Fritz_Box_HW247*) FULLSIZE=0x10000000 ;; # 7520 (256 MB) Fritz_Box_HW258*) FULLSIZE=0x20000000 ;; # 6850 5G (512 MB) Fritz_Box_HW262*) FULLSIZE=0x20000000 ;; # 6850 4G (512 MB) Fritz_Box_HW276*) FULLSIZE=0x10000000 ;; # 7521 (256 MB) # BCM Fritz_Box_HW224*) FULLSIZE=0x20000000 ;; # 7581 (512 MB) Fritz_Box_HW228*) FULLSIZE=0x20000000 ;; # 7582 (512 MB) # FIT Fritz_Box_HW253*) FULLSIZE=0x40000000 ;; # 6000 (1.0 GB) Fritz_Box_HW256*) FULLSIZE=0x20000000 ;; # 7539 (512 MB) Fritz_Box_HW257*) FULLSIZE=0x40000000 ;; # 5530 (1.0 GB) Fritz_Box_HW261*) FULLSIZE=0x40000000 ;; # 4060 (1.0 GB) Fritz_Box_HW268*) FULLSIZE=0x10000000 ;; # 1209 (256 MB) # Fritz_Box_HW270*) FULLSIZE=0x?0000000 ;; # 3009 (??? MB) Fritz_Box_HW271*) FULLSIZE=0x20000000 ;; # 7510 (512 MB) Fritz_Box_HW272*) FULLSIZE=0x40000000 ;; # 5590 (1.0 GB) *) [ $ISRAM ] && FULLSIZE=0x08000000 # 128 MB [ $ISFIT ] && FULLSIZE=0x18000000 # 384 MB ;; esac fi [ "${FULLSIZE//0/}" == "x" ] && OUTVAL="<detect>" || OUTVAL="$(( $FULLSIZE /1024/1024 )) MB" if [ -z "$ALIBYTES" ]; then [ $ISRAM ] && ALIBYTES="$(( 1024 * 0 ))" [ $ISFIT ] && ALIBYTES="$(( 1024 * 64 ))" fi echo " * Allowed memory size: $OUTVAL" fi if [ $ISFIT ]; then [ $NOAFU ] && AFU="" || AFU="avm_fwupdate " fi if [ ! $ISSINGLE ]; then [ -n "$LFS" ] && OUTVAL="$LFS" [ -z "$LFS" ] && OUTVAL="<other>" [ "$LFS" == "9" ] && OUTVAL="<current>" [ $ISFIT ] && OUTVAL="<other>" 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