#!/bin/bash # Freetz script to modify AVM FRITZ!Box and OEM firmware images # # Copyright (C) 2005-2006 Daniel Eiband # Copyright (C) 2006-2018 by the Freetz developers (http://freetz.org) # Copyright (C) 2019 by Freetz developers (https://freetz-ng.github.io/ and https://freetz.github.io) # # Licensed under the GPL v2, see the file COPYING in this tarball. # # This script is based on Christian Volkmann's fritzbox mod-0.57. # Legacy URL: http://www.ip-phone-forum.de/showthread.php?t=65894 # # Special thanks to Andreas Buehmann, Christian Volkmann, Enrik Berkhan, # SpeedyBZ and all members on ip-phone-forum.de who contributed to this mod. usage() { cat << EOF Usage: $SELF [-u|-m|-p|-a] [-s] [-v [-w [-x ]]] [-z] [-c ] [-n] [-f] [-i ] [-d ] [ []] main actions -u unpack firmware image -m modify previously unpacked image -p pack firmware image -a all: unpack, modify and pack firmware image special actions -s sign firmware image -v validate firmware image with the pub key (not for recovery.exe) -w validate 2nd firmware image with the pub key (not for recovery.exe) -x validate 3rd firmware image with the pub key (not for recovery.exe) -z zip file system into archive for USB/NFS root -c copy file system to target directory for NFS/USB root (implies -z) options -n firmware-nocompile: do not install kernel and busybox -f force pack even if image is too big for flash (AVM SDK) input/output -i input file for configuration data (default: .config) -d build directory (default: .mod) original firmware name 2nd firmware name (e.g. for merging in web UI) 3rd firmware name (e.g. to borrow missing files) EOF } ################################################## ## Initialise and check command line parameters ## ################################################## # This script's name ("fwmod" if not linked/renamed) SELF="$(basename "$0")" # No parameters -> print usage info to stdout [ $# -eq 0 ] && usage && exit 0 # Backup command line parameters [$0..$n] to save them from getopts eating them # away, because we need them again later for the recursive fakerooted call. for ((i=0; i<=$#; i++)); do CMDLINE_ORIG[i]="${!i}" done # Default values for unset command line parameters DOT_CONFIG="$(dirname "$0")/.config" DO_UNPACK=0; DO_MOD=0; DO_PACK=0; DO_SIGN=0; DO_VALIDATE=0; DO_VALIDATE2=0; DO_VALIDATE3=0 FIRMWARE_NOCOMPILE=0; FORCE_PACK=0; DO_ZIP=0; COPY_FS_DIR=; DIR= # Parse command line parameters while getopts umpsanfzc:i:d:v:w:x: opt; do case "$opt" in u) DO_UNPACK=1 ;; m) DO_MOD=1 ;; p) DO_PACK=1 ;; v) DO_VALIDATE=1; FIRMWARE_PUB="$OPTARG" ;; w) DO_VALIDATE2=1; FIRMWARE2_PUB="$OPTARG" ;; x) DO_VALIDATE3=1; FIRMWARE3_PUB="$OPTARG" ;; s) DO_SIGN=1 ;; a) DO_UNPACK=1; DO_MOD=1; DO_PACK=1 ;; n) FIRMWARE_NOCOMPILE=1 ;; f) FORCE_PACK=1 ;; z) DO_ZIP=1 ;; c) COPY_FS_DIR="$OPTARG"; [ "$COPY_FS_DIR" ] && DO_ZIP=1 ;; i) DOT_CONFIG="$OPTARG" ;; d) DIR="$OPTARG" ;; *) usage >&2; exit 1 ;; esac done shift $((OPTIND-1)) # At least one action and one (non-empty) firmware image name must be specified [ $(($DO_UNPACK + $DO_MOD + $DO_PACK + $DO_ZIP + $DO_VALIDATE)) -eq 0 -o $# -lt 1 -o $# -gt 3 -o ! "$1" ] && usage >&2 && exit 1 # Check if it's a completely automated run in the "no freetz"-mode and cache the value. # We are interested in what the user asked us for and not what we are actually doing, # the UNPACK step might be skipped (and the value of DO_UNPACK changed) if the already # unpacked firmware is found on the disk. [ "$DO_UNPACK" -gt 0 -a "$DO_MOD" -eq 0 -a "$DO_PACK" -gt 0 ] && NO_FREETZ_AUTOMATED_RUN=1 || NO_FREETZ_AUTOMATED_RUN=0 # Freetz base + tools directories BASE_DIR="$(dirname "$0")" ABS_BASE_DIR="$(readlink -f "$BASE_DIR")" TOOLS_DIR="${ABS_BASE_DIR}/tools" # Include common helper functions (isFreetzType, echo*, error, modunsqfs* etc.) source "${TOOLS_DIR}/freetz_functions" || (echo "cannot find script freetz_functions" >&2; exit 1) [ ! -x "${TOOLS_DIR}/busybox" ] && \ error 1 "Can not find host tools, please run 'make tools' first." [ "$DO_SIGN" -gt 0 -a $(($DO_PACK + $DO_ZIP)) -eq 0 ] && \ error 1 "Firmware signing without packing is not supported. Please use PeterPawn's sign_image tool to sign an already existing .image file." [ $(($DO_SIGN + $DO_VALIDATE + $DO_VALIDATE2 + $DO_VALIDATE3 )) -gt 0 -a ! -x "$(command -v openssl)" ] && \ error 1 "OpenSSL is required to verify and create image signature. Please install it or disable the option(s) in menuconfig." # Initialise firmware image names FIRMWARE="$1" FIRMWARE2="$2" FIRMWARE3="$3" FIRMWARE_EXTENSION="${FIRMWARE##*.}" FIRMWARE_EXTENSION="${FIRMWARE_EXTENSION,,}" # Given firmware image(s) must exist [ -r "$FIRMWARE" ] || error 1 "firmware image $(basename "$FIRMWARE") not found" [ "$FIRMWARE2" -a ! -r "$FIRMWARE2" ] && error 1 "firmware image $(basename "$FIRMWARE2") not found" [ "$FIRMWARE3" -a ! -r "$FIRMWARE3" ] && error 1 "firmware image $(basename "$FIRMWARE3") not found" # Config file must exist [ -r "$DOT_CONFIG" ] || error 1 "not configured" # Set default output directory, if not specified on command line : ${DIR:=$FIRMWARE.mod} # Create output directory if not yet exists (not in validate only mode) [ $(($DO_UNPACK + $DO_MOD + $DO_PACK + $DO_ZIP )) -ne 0 ] && mkdir -p "$DIR" ################################# ## Initialise script variables ## ################################# # Relative subdirectories SOURCE_SUBDIR="source" FIRMWARE_SUBDIR="firmware" FITIMAGE_SUBDIR="fit-image" FILESYSTEM_SUBDIR="filesystem" FILESYSTEM_OUTER_SUBDIR="filesystem.outer" AVMPLUGINS_SUBDIR="plugins.image" EXTERNAL_SUBDIR="external" KERNEL_SUBDIR="kernel" VARTAR_SUBDIR="var.tar" SIGNATURE_SUBDIR=".signature" HTML_SUBDIR="usr/www" GRAPHICS_SUBDIR="graphics" # (temporary) files created during firmware unpacking RAW_KERNEL_FILE="kernel.raw" RAW_HIDDEN_FILE="kernelsquashfs.raw" VARTAR_FILE="var.tar" UNPACKED_FILE="$DIR/.unpacked" # Path to bash (shell required by fwmod) SHELL=$BASH # Tools used by fwmod FINDSQUASHFS_TOOL="find-squashfs" TICHKSUM_TOOL="tichksum" MAKEDEVS_TOOL="makedevs" DEBUGFS_TOOL="debugfs" EXTERNAL_TOOL="external" TAR_TOOL="tar" TAR_GNU_TOOL="tar-gnu" MD5SUM_TOOL="md5sum" BUSYBOX_TOOL="busybox" # Optional tools PV="$(command -v pv >/dev/null && echo 'pv -rcb')" # Absolute tools paths EXTERNAL="${TOOLS_DIR}/${EXTERNAL_TOOL}" DEBUGFS="${TOOLS_DIR}/${DEBUGFS_TOOL}" FINDSQUASHFS="${TOOLS_DIR}/${FINDSQUASHFS_TOOL}" TICHKSUM="${TOOLS_DIR}/${TICHKSUM_TOOL}" MAKEDEVS="${TOOLS_DIR}/${MAKEDEVS_TOOL}" MAKEDEVS_FILE="${TOOLS_DIR}/device.table" TAR="${TOOLS_DIR}/${TAR_TOOL}" TAR_GNU="${TOOLS_DIR}/${TAR_GNU_TOOL}" MD5SUM="${TOOLS_DIR}/${MD5SUM_TOOL}" BUSYBOX="${TOOLS_DIR}/${BUSYBOX_TOOL}" BLKID="${TOOLS_DIR}/blkid" # Freetz directores relative to base dir PACKAGES_DIR_ROOT="${BASE_DIR}/packages" PATCHES_DIR="${BASE_DIR}/patches" PATCHES_COND_DIR="${PATCHES_DIR}/cond" PATCHES_DEVICES_DIR="${PATCHES_DIR}/devices" PATCHES_SCRIPTS_DIR="${PATCHES_DIR}/scripts" ROOT_DIR="${BASE_DIR}/root" KERNEL_REP_DIR="${BASE_DIR}/kernel" ADDON_DIR="${BASE_DIR}/addon" GRAPHICS_DIR="${BASE_DIR}/${GRAPHICS_SUBDIR}" # Freetz branding directories relative to graphics subdirectory FAVICON_DIR="${GRAPHICS_DIR}/favicon" TAGGING_DIR="${GRAPHICS_DIR}/tagging" # Package files PACKAGES_LIST_FILE="${BASE_DIR}/.packages" STATIC_ADDON_FILES="${ADDON_DIR}/*.pkg" # Alien variables TK_DIR="${DIR}/.tk/original" FIRMWARE_TK_DIR="${TK_DIR}/${FIRMWARE_SUBDIR}" FILESYSTEM_TK_DIR="${TK_DIR}/${FILESYSTEM_SUBDIR}" KERNEL_TK_DIR="${TK_DIR}/${KERNEL_SUBDIR}" VARTAR_TK_DIR="${KERNEL_TK_DIR}/${VARTAR_SUBDIR}" AUX_DIR="${DIR}/.aux/original" FIRMWARE_AUX_DIR="${AUX_DIR}/${FIRMWARE_SUBDIR}" FILESYSTEM_AUX_DIR="${AUX_DIR}/${FILESYSTEM_SUBDIR}" KERNEL_AUX_DIR="${AUX_DIR}/${KERNEL_SUBDIR}" VARTAR_AUX_DIR="${KERNEL_AUX_DIR}/${VARTAR_SUBDIR}" ########################################################## ## Include config file + initialise some more variables ## ########################################################## # Include config file, but do not override variables which are already defined # in the environment, e.g. via "make FREETZ_SOMETHING=y" sed -nr 's/^([^=]+)=(.*)/: ${\1:=\2}/p' "$DOT_CONFIG" > "$DOT_CONFIG.fwmod" source "$DOT_CONFIG.fwmod" rm "$DOT_CONFIG.fwmod" # Set default verbosity level, just in case none was defined in the (possibly # user-defined and minimal) config file : ${FREETZ_VERBOSITY_LEVEL:=0} [ "$FREETZ_VERBOSITY_LEVEL" -lt 2 ] && PV='' # Kernel/SquashFS images contained in firmware KERNEL_IMAGE="${FREETZ_AVM_IMAGES_SUBDIR}/kernel.image" FILESYSTEM_IMAGE="${FREETZ_AVM_IMAGES_SUBDIR}/filesystem.image" FILESYSTEM_INNER_IMAGE="filesystem_core.squashfs" AVMPLUGINS_FILE="${FREETZ_AVM_IMAGES_SUBDIR}/plugins.update" # Use FREETZ_TARGET_CROSS to determine build tool paths NM="${ABS_BASE_DIR}/toolchain/target/bin/${FREETZ_TARGET_CROSS}nm" STRIP="${ABS_BASE_DIR}/toolchain/target/bin/${FREETZ_TARGET_CROSS}strip" # Tools and options for (un)packing SquashFS UNSQUASHFS_TOOL="unsquashfs4-avm-${FREETZ_AVM_SQUASHFS_ENDIANNESS}" UNSQUASHFS="${TOOLS_DIR}/${UNSQUASHFS_TOOL}" UNSQUASHFS_OPTIONS="-no-progress -exit-on-error" MKSQUASHFS_TOOL[2]="mksquashfs2-lzma" MKSQUASHFS_TOOL[3]="mksquashfs3-multi" MKSQUASHFS_TOOL[4]="mksquashfs4-avm-${FREETZ_AVM_SQUASHFS_ENDIANNESS}" MKSQUASHFS="${TOOLS_DIR}/${MKSQUASHFS_TOOL[${FREETZ_SQUASHFS_VERSION}]}" MKSQUASHFS_OPTIONS="-all-root -info" if [ "${FREETZ_SQUASHFS_VERSION}" -gt 2 ]; then MKSQUASHFS_OPTIONS+=" -no-progress -no-exports -no-sparse" fi if [ "${FREETZ_SQUASHFS_VERSION}" -lt 4 ]; then MKSQUASHFS_OPTIONS+=" -noappend" MKSQUASHFS_OPTIONS+=" -${FREETZ_AVM_SQUASHFS_ENDIANNESS}" fi if [ "${FREETZ_SQUASHFS_VERSION}" -eq 3 -a "${FREETZ_AVM_SQUASHFS_COMPRESSION}" == "lzma" ]; then MKSQUASHFS_OPTIONS+=" -lzma1" fi ################################# ## Validate firmware signature ## ################################# # validate_signature # $1 ("1") when signature validating is enabled # $2 (img) the .image file to validate # $3 (key) public key, format: "EXPONENTxMODULUS". If no EXPONENT is given, default 010001 will be used (as in all images at the moment) validate_signature() { echo -n "checking signature: " [ "$1" != "1" ] && echo -e "\033[1;33mdisabled\033[0m" && return [ -z "$3" ] && echo -e "\033[1;34munknown\033[0m" && error 1 "no public key available to validate signature" # var local TMP="$(mktemp -dt freetz-sig-XXX)" local MOD="${3#*x}" local EXP="${3%x*}" [ "$EXP" == "$MOD" ] && EXP='010001' if [ "$FREETZ_FWMOD_VALIDATE_METHOD_SI" == "y" ]; then echo -e "$MOD\n$EXP" > "$TMP/sig" ${TOOLS_DIR}/yf/signimage/yf_check_signature "$2" -a "$TMP/sig" 2> "$TMP/out" RET=$? [ $RET -ne 0 ] && echo -e "\033[0;31mfailed\033[0m" && cat "$TMP/out" rm -rf "$TMP" [ $RET -ne 0 ] && error $RET "image could not be verified with public key" else # img cat "$2" > "$TMP/img" # fix local FIX="$(mktemp -p $TMP)" "$TAR_GNU" -f "$TMP/img" --owner=0 --group=0 --mode=0755 --format=oldgnu -C "$TMP" --append ${FIX##*/} # sig "$TAR_GNU" -f "$TMP/img" --owner=0 --group=0 --mode=0755 --format=oldgnu -C "$TMP" --extract ./var/signature --transform='s!.*!sig!' "$TAR_GNU" -f "$TMP/img" --owner=0 --group=0 --mode=0755 --format=oldgnu --delete ./var/signature ${FIX##*/} # key { echo -n 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQ==' | base64 -d echo -n "$MOD" | while read -n2 x; do echo -ne "\x$x"; done echo -ne "\x2" echo -ne "\x$((${#EXP}/2))" echo -n "$EXP" | while read -n2 x; do echo -ne "\x$x"; done } > "$TMP/key" # chk VAL="$(openssl md5 -verify "$TMP/key" -keyform der -signature "$TMP/sig" "$TMP/img" 2>&1)" RET="$?" # clr rm -rf "$TMP" # act [ "$RET" != "0" ] && echo -e "\033[0;31mfailed\033[0m\nOpenSSL: $VAL" && error 1 "image could not be verified with public key" fi echo -e "\033[0;32mvalid\033[0m" } # validate_signature only [ $DO_VALIDATE -eq 1 -a $(($DO_UNPACK + $DO_MOD + $DO_PACK + $DO_ZIP)) -eq 0 ] && validate_signature "$DO_VALIDATE" "$FIRMWARE" "$FIRMWARE_PUB" && exit 0 ####################################### ## Initialise fakeroot incl. caching ## ####################################### # Create id string based on MD5 hashes of firmware images FIRMWARE_MD5="$("$MD5SUM" "$FIRMWARE" | cut -d ' ' -f 1)" [ "$FIRMWARE2" ] && FIRMWARE_MD5="$FIRMWARE_MD5-$("$MD5SUM" "$FIRMWARE2" | cut -d ' ' -f 1)" [ "$FREETZ_ROOTEMU_FAKEROOT" != 'y' ] && FIRMWARE_MD5="$FIRMWARE_MD5-pseudo" || FIRMWARE_MD5="$FIRMWARE_MD5-fakeroot" FAKEROOT_CACHE_DIR="$ABS_BASE_DIR/.fakeroot-cache" [ "$FREETZ_ROOTEMU_FAKEROOT" != 'y' ] && FAKEROOT_CACHE_DB="$FAKEROOT_CACHE_DIR/files.db" || FAKEROOT_CACHE_DB="$FAKEROOT_CACHE_DIR/fakeroot.cvs" # Are we in a fakeroot context? if [ -n "$FWMOD_RECURSIVE" ] && [ $UID -eq 0 ]; then # Yes -> fakeroot is active # Make sure fakeroot call came from ourselves so we can assume the cache settings to be correct if [ $((FWMOD_RECURSIVE)) -eq 0 ] || [ "$SELF" != "$(sed -nr 's/^Name:[[:blank:]]+(.*)/\1/p' /proc/$FWMOD_RECURSIVE/status)" ]; then error 1 "$SELF must not run in a fakeroot environment" fi # Has current combination of firmware already been unpacked? if [ "$(cat "$UNPACKED_FILE" 2>/dev/null)" == "$FIRMWARE_MD5" ]; then # Yes -> skip unpack [ $DO_UNPACK -gt 0 ] && SKIP_UNPACK="STEP 1: UNPACK (SKIPPED)\n\n" DO_UNPACK=0 else # No -> force unpack [ $DO_UNPACK -eq 0 ] && FORCE_UNPACK=" (FORCED)" DO_UNPACK=1 fi else # No -> fakeroot is inactive if [ "$(cat "$UNPACKED_FILE" 2>/dev/null)" != "$FIRMWARE_MD5" ]; then # Dont keep old databases on a new unpack mkdir -p "$FAKEROOT_CACHE_DIR" rm -f $FAKEROOT_CACHE_DIR/* fi if [ "$FREETZ_ROOTEMU_FAKEROOT" != 'y' ]; then PSEUDO_PREFIX="$TOOLS_DIR/build" PSEUDO_LOCALSTATEDIR="$FAKEROOT_CACHE_DIR" "$TOOLS_DIR/build/bin/pseudo" -B &>/dev/null #scan FWMOD_RECURSIVE="$$" PSEUDO_PREFIX="$TOOLS_DIR/build" PSEUDO_LOCALSTATEDIR="$FAKEROOT_CACHE_DIR" PSEUDO_DEBUG="0" "$TOOLS_DIR/build/bin/pseudo" '--' "${CMDLINE_ORIG[@]}" PSEUDO_PREFIX="$TOOLS_DIR/build" PSEUDO_LOCALSTATEDIR="$FAKEROOT_CACHE_DIR" "$TOOLS_DIR/build/bin/pseudo" -S &>/dev/null #halt else # Has current combination of firmware already been unpacked? if [ "$(cat "$UNPACKED_FILE" 2>/dev/null)" == "$FIRMWARE_MD5" ]; then # Yes -> use existing cache and firmwares (no unpack necessary) NON_FAKEROOT_USERNAME=$(id -u -n) FWMOD_RECURSIVE=$$ $TOOLS_DIR/build/bin/fakeroot -i "$FAKEROOT_CACHE_DB" -s "$FAKEROOT_CACHE_DB" '--' "${CMDLINE_ORIG[@]}" else # No -> create new fakeroot cache and unpack firmwares NON_FAKEROOT_USERNAME=$(id -u -n) FWMOD_RECURSIVE=$$ $TOOLS_DIR/build/bin/fakeroot -s "$FAKEROOT_CACHE_DB" '--' "${CMDLINE_ORIG[@]}" fi fi retval=$? [ $retval -eq 0 ] || exit $retval # ------------------------------------------------------------------ # -- Copy file system to target folder (NFS root, maybe USB root) -- # ------------------------------------------------------------------ # This cannot be done in the pack/zip section (needs real sudo, not fakeroot) if [ "$COPY_FS_DIR" ]; then echo0 "copying root file system to directory $COPY_FS_DIR" rootfs_archive="$(cat "${DIR}/.rootfs_archive")" || error 1 "cannot determine root file system archive name" [ -d "$COPY_FS_DIR" ] && (sudo rm -rf "$COPY_FS_DIR"/* || error 1 "cannot clean up directory $COPY_FS_DIR") mkdir -p "$COPY_FS_DIR" || error 1 "cannot create directory $COPY_FS_DIR" sudo "$TAR" -C "$COPY_FS_DIR" -xf "$rootfs_archive" || error 1 "cannot unpack root file system" echo -e "done.\n" fi echo0 -b "FINISHED" exit 0 fi ############################################ ## Unpack and unsquash the firmware image ## ############################################ ORG_DIR="${DIR}/original" FIRMWARE_DIR="${ORG_DIR}/${FIRMWARE_SUBDIR}" FITIMAGE_DIR="${ORG_DIR}/${FITIMAGE_SUBDIR}" FILESYSTEM_DIR="${ORG_DIR}/${FILESYSTEM_SUBDIR}" FILESYSTEM_OUTER_DIR="${ORG_DIR}/${FILESYSTEM_OUTER_SUBDIR}" KERNEL_DIR="${ORG_DIR}/${KERNEL_SUBDIR}" AVMPLUGINS_DIR="${KERNEL_DIR}/${AVMPLUGINS_SUBDIR}" VARTAR_DIR="${KERNEL_DIR}/${VARTAR_SUBDIR}" HTML_DIR="${FILESYSTEM_DIR}/${HTML_SUBDIR}" RAW_KERNEL="${KERNEL_DIR}/${RAW_KERNEL_FILE}" RAW_FILESYSTEM="${KERNEL_DIR}/${RAW_HIDDEN_FILE}" KERNEL="${FIRMWARE_DIR}/${KERNEL_IMAGE}" if [ "${FREETZ_AVM_HAS_SEPARATE_FILESYSTEM_IMAGE}" == "y" ]; then if [ "${FREETZ_AVM_HAS_INNER_OUTER_FILESYSTEM}" == "y" ]; then FILESYSTEM="${FILESYSTEM_OUTER_DIR}/${FILESYSTEM_INNER_IMAGE}" INNER_FS_PREFIX="inner-" else FILESYSTEM="${FIRMWARE_DIR}/${FILESYSTEM_IMAGE}" fi else FILESYSTEM="${RAW_FILESYSTEM}" fi AVMPLUGINS="${FIRMWARE_DIR}/${AVMPLUGINS_FILE}" VARTAR="${FILESYSTEM_DIR}/${VARTAR_FILE}" # avm image details function image_details() { local AVM_FW_PRODUCT local AVM_FW_LANGUAGE #AVM_FW_MAJOR #AVM_FW_VERSION local AVM_FW_LABOR #AVM_FW_REVISION local AVM_FW_DATE local AVM_FW_CYCLE local AVM_FM_REGION #SOURCE_IMAGE_DETAILS # AVM_FW_PRODUCT="$(sed -rn 's/Annex./Annex/;s/export CONFIG_PRODUKT_NAME=".*([0-9]{3}[0-9V].*)"/\1/p' ${FILESYSTEM_DIR}/etc/init.d/rc.conf | head -n1)" # 4-digits in /etc/init.d/rc.conf [ -z "${AVM_FW_PRODUCT}" ] && AVM_FW_PRODUCT="$(sed -rn 's/export CONFIG_PRODUKT_NAME="(FRITZ!Box|Speedport|Sinus|Eumex) ([^"]+)"/\2/p' ${FILESYSTEM_DIR}/etc/init.d/rc.conf | head -n1 | tr ' ' '-')" # symbolic name in /etc/init.d/rc.conf if [ -e "${FILESYSTEM_DIR}/etc/init.d/rc.init" ]; then # /etc/init.d/rc.init is not available in all firmwares [ -z "${AVM_FW_PRODUCT}" ] && AVM_FW_PRODUCT="$(sed -rn 's/^HW=[0-9]* OEM=all _PRODUKT_NAME=(FRITZ!Box|Speedport|Sinus|Eumex)#//p' ${FILESYSTEM_DIR}/etc/init.d/rc.init | head -n1 | sed 's/#//g;s/Annex.//;s/WLAN/-&/g;s/^$/FritzBox/g')" # symbolic name in /etc/init.d/rc.init [ -z "${AVM_FW_PRODUCT}" ] && AVM_FW_PRODUCT="$(sed -rn 's/^HW=[0-9]* OEM=all _PRODUKT_NAME=([0-9A-Z\#]{4,6}).*/\1/p' ${FILESYSTEM_DIR}/etc/init.d/rc.init)" # 4-digits in /etc/init.d/rc.init fi [ -z "${AVM_FW_PRODUCT}" ] && AVM_FW_PRODUCT="$(sed -rn 's/export CONFIG_PRODUKT_NAME=.*(Repeater|Powerline) (.*)"/\2/p' ${FILESYSTEM_DIR}/etc/init.d/rc.conf)" # Repeater like 'DVB-C' [ -z "${AVM_FW_PRODUCT}" ] && warn "Failed to determine AVM_FW_PRODUCT, even though this is a cosmetic bug only please report it to the Freetz developers and provide your .config" AVM_FW_PRODUCT="${AVM_FW_PRODUCT%% Edition*}" AVM_FW_PRODUCT="${AVM_FW_PRODUCT% }" AVM_FW_LANGUAGE="$(sed -n 's/^language /_/p' ${FILESYSTEM_DIR}/etc/default.language)" #primary language AVM_FW_LANGUAGE="${AVM_FW_LANGUAGE}$(for x in $(ls ${FILESYSTEM_DIR}/etc/htmltext_??.db 2>/dev/null| sed 's/.*_//g;s/\.db//g'); do [ "_$x" != "${AVM_FW_LANGUAGE}" ] && echo -en "-$x"; done; echo)" # other languages AVM_FW_MAJOR="$(sed -rn 's/^export CONFIG_VERSION_MAJOR="(.*)"/\1/p' ${FILESYSTEM_DIR}/etc/init.d/rc.conf | tail -n1)" # newer firmware [ -z "${AVM_FW_MAJOR}" ] && AVM_FW_MAJOR="$(sed -n 's/^HW=[0-9].*VERSION_MAJOR=//p' ${FILESYSTEM_DIR}/etc/init.d/rc.init)" # older firmware AVM_FW_VERSION="$(sed -n 's/^export FIRMWARE_VERSION=.*}[.]//p' ${FILESYSTEM_DIR}/etc/version)" # older firmware [ -z "$AVM_FW_VERSION" ] && AVM_FW_VERSION="$(sed -rn 's/^export CONFIG_VERSION=\"?([^\"]*)\"?/\1/p' ${FILESYSTEM_DIR}/etc/init.d/rc.conf)" # newer firmware AVM_FW_LABOR="$(sed -rn 's/^export CONFIG_LABOR_ID_NAME="(.*)"/-\1/p' ${FILESYSTEM_DIR}/etc/init.d/rc.conf)" AVM_FW_REVISION="$(sed -n '/--project)$/{N;s/.*echo //p}' ${FILESYSTEM_DIR}/etc/version)" # older firmware [ -z "$AVM_FW_REVISION" ] && AVM_FW_REVISION="$(sed -rn 's/^export CONFIG_SUBVERSION=\"?-?([^\"]*)\"?/\1/p' ${FILESYSTEM_DIR}/etc/init.d/rc.conf)" # newer firmware [ -z "$AVM_FW_REVISION" ] && AVM_FW_REVISION="$(sed -rn 's/^export CONFIG_BUILDNUMBER=\"([^\"]*)\"/\1/p' ${FILESYSTEM_DIR}/etc/init.d/rc.conf)" # latest firmware AVM_FW_DATE="$(sed -rn 's/^export FIRMWARE_DATE="(.*)"/\1/p' ${FILESYSTEM_DIR}/etc/version)" # older firmware [ -z "$AVM_FW_DATE" ] && AVM_FW_DATE="$(date -d"$(stat -c '%y' ${FILESYSTEM_DIR}/etc/version)" "+%d.%m.%Y %H:%M:%S")" # newer firmware AVM_FW_CYCLE="$(sed -rn 's/^Releasecycle=//p' "${FIRMWARE_DIR}/var/content" 2>/dev/null)" [ -n "$AVM_FW_CYCLE" ] && AVM_FW_CYCLE=" [$AVM_FW_CYCLE]" [ -d ${FILESYSTEM_DIR}/etc/default.*/avm/ ] && AVM_FM_REGION='GER' [ -d ${FILESYSTEM_DIR}/etc/default.*/avme/ ] && AVM_FM_REGION='INT' [ -d ${FILESYSTEM_DIR}/etc/default.*/avme/ -a -d ${FILESYSTEM_DIR}/etc/default.*/avm/ ] && AVM_FM_REGION='ALL' [ "$FREETZ_TYPE_LANG_IT" == "y" ] && AVM_FM_REGION='ITA' [ "$FREETZ_TYPE_LANG_A_CH" == "y" ] && AVM_FM_REGION='ACH' # SOURCE_IMAGE_DETAILS="${AVM_FW_PRODUCT/ /-}${AVM_FW_LANGUAGE} ${AVM_FW_MAJOR}.${AVM_FW_VERSION}${AVM_FW_LABOR} rev${AVM_FW_REVISION} {${AVM_FM_REGION}}${AVM_FW_CYCLE} (${AVM_FW_DATE})" } echo STEP="1" if [ "$DO_UNPACK" -gt 0 ]; then [ "$FIRMWARE2" ] && UNPACK_SUBSTEP="A" && UNPACK_MAIN=" 1ST" echo0 -b "STEP 1${UNPACK_SUBSTEP}: UNPACK${UNPACK_MAIN}${FORCE_UNPACK}" # Remove old "unpacked" marker to avoid an undefined state in case of # interruption before unpacking operation is finished rm -f "$UNPACKED_FILE" REAL_FIRMWARE="$(readlink ${FIRMWARE} 2>/dev/null || echo ${FIRMWARE##*/})" echo2 -l "source firmware file: ${FIRMWARE/${FIRMWARE##*\/}/$REAL_FIRMWARE}" rm -rf "$ORG_DIR" mkdir "$ORG_DIR" # validate_signature if [ "$FIRMWARE_EXTENSION" == "cvc" ]; then [ $DO_VALIDATE -ne 1 ] && validate_signature "$DO_VALIDATE" elif [ "$FIRMWARE_EXTENSION" != "exe" ]; then validate_signature "$DO_VALIDATE" "$FIRMWARE" "$FIRMWARE_PUB" else validate_signature "0" fi echo "unpacking firmware image" mkdir "$FIRMWARE_DIR" if [ "$FIRMWARE_EXTENSION" == "cvc" ]; then # Check and skip garbage (cvc&p7b) image_size="0x$(printf "%08X\n" $(stat -c %s "$FIRMWARE"))" image_grbg="$($TOOLS_DIR/sfk hexfind "$FIRMWARE" _./var/_ | sed -n 's/.*hit at offset //p' |head -n1)" [ -n "$image_grbg" ] && echo "Skipping $(($image_grbg)) Bytes garbage" # validate_signature if [ $DO_VALIDATE -eq 1 ]; then TMP_SIG="$(mktemp -t freetz-sig-XXX)" tail -c $(( $image_size - ${image_grbg:-0x0} )) "$FIRMWARE" > "$TMP_SIG" validate_signature "$DO_VALIDATE" "$TMP_SIG" "$FIRMWARE_PUB" rm "$TMP_SIG" fi # Unpack standard *.image file in tar format tail -c $(( $image_size - ${image_grbg:-0x0} )) "$FIRMWARE" | \ "$TAR_GNU" -x -C "$FIRMWARE_DIR" || untar_failed=1 elif [ "$FIRMWARE_EXTENSION" != "exe" ]; then # Unpack standard *.image file in tar format "$TAR_GNU" -xif "$FIRMWARE" -C "$FIRMWARE_DIR" || untar_failed=1 fi if [ "$FIRMWARE_EXTENSION" == "exe" ] || [ "$untar_failed" ]; then # Unpack Windows recover.exe file or mtdblock dump exe_images=($("${TOOLS_DIR}/extract-images" "$ABS_BASE_DIR" "$FIRMWARE" | sed -nr 's/^ *(.*\.image) - .*/\1/p')) [ "$exe_images" ] || error 1 "unpacking failed" mkdir -p "$FIRMWARE_DIR/${FREETZ_AVM_IMAGES_SUBDIR}" mkdir "$KERNEL_DIR" unset exe_hr_mode # NOTE: This loop is sensitive to the order and format of output of # "tools/extract-images", e.g. a hidden root image is always listed # before its parts. for (( i=0; i<${#exe_images[@]}; i++ )); do exe_image="${exe_images[i]}" case "$exe_image" in */urlader.image) mv "$exe_image" "$FIRMWARE_DIR/${FREETZ_AVM_IMAGES_SUBDIR}" ;; */hr_kernel.image) exe_hr_mode=1 mv "$exe_image" "$FIRMWARE_DIR/${FREETZ_AVM_IMAGES_SUBDIR}/kernel.image" touch "$FIRMWARE_DIR/${FREETZ_AVM_IMAGES_SUBDIR}/filesystem.image" ;; */kernel.image) [ "$exe_hr_mode" ] || cp "$exe_image" "$FIRMWARE_DIR/${FREETZ_AVM_IMAGES_SUBDIR}/kernel.image" mv "$exe_image" "$KERNEL_DIR/kernel.raw" ;; */filesystem.image) if [ "$exe_hr_mode" ]; then mv "$exe_image" "$KERNEL_DIR/kernelsquashfs.raw" else mv "$exe_image" "$FIRMWARE_DIR/${FREETZ_AVM_IMAGES_SUBDIR}/filesystem.image" fi ;; esac done rm -r "$(dirname "$exe_image")" fi if [ -e "$FIRMWARE_DIR/var/firmware-update.uimg" ]; then echo0 "unpacking uimg file" "${TOOLS_DIR}/uimg" -u "$FIRMWARE_DIR/var/firmware-update.uimg" >/dev/null chmod +w $FIRMWARE_DIR/var/*.bin mkdir -p "$FIRMWARE_DIR/var/remote/var/tmp/x86" ln $FIRMWARE_DIR/var/*_ATOM_ROOTFS.bin "$FIRMWARE_DIR/var/remote/var/tmp/x86/filesystem.image" ln $FIRMWARE_DIR/var/*_ATOM_KERNEL.bin "$FIRMWARE_DIR/var/remote/var/tmp/x86/kernel.image" elif [ -e "$FIRMWARE_DIR/var/tmp/fit-image" ]; then echo0 "unpacking fitimg file" $TOOLS_DIR/fit.sh unpack "$FIRMWARE_DIR/var/tmp/fit-image" "$FITIMAGE_DIR" || error 1 "unpacking failed" for x in kernel filesystem; do ln $FITIMAGE_DIR/$x.image $FIRMWARE_DIR/var/tmp/; done fi # Do the images exist ? [ ! -r "${KERNEL}" ] && error 1 "cannot find kernel.image (${KERNEL})" [ ! -r "${FIRMWARE_DIR}/${FILESYSTEM_IMAGE}" ] && error 1 "cannot find filesystem.image (${FIRMWARE_DIR}/${FILESYSTEM_IMAGE})" # Do we have the tool ? for tool in "$UNSQUASHFS" "$FINDSQUASHFS" "$TICHKSUM"; do [ ! -x $tool ] && error 1 "cannot find the tool $tool" done # Is cpio up to date ? if [ "$FREETZ_AVM_PROP_INNER_FILESYSTEM_TYPE_CPIO" == "y" ]; then [ -z "$(cpio --version 2>/dev/null | sed -nr 's/^cpio .* 2\.([0-9]*)(\.[0-9]+)*/\1/p' | sed -r 's/^([0-9]|10|11)$//')" ] && \ error 1 "cpio version 2.12 is required" fi # Remove NMI vector from SquashFS if [ "$FREETZ_AVM_HAS_NMI_VECTOR" == "y" ]; then echo0 "removing NMI vector from SquashFS" [ "$FREETZ_AVM_HAS_SEPARATE_FILESYSTEM_IMAGE" == "y" ] && FILE_WITH_NMI_VECTOR_TO_PROCESS="${FIRMWARE_DIR}/${FILESYSTEM_IMAGE}" || FILE_WITH_NMI_VECTOR_TO_PROCESS="$KERNEL" if [ "$FREETZ_VERBOSITY_LEVEL" -lt 2 ]; then "$TOOLS_DIR/remove-nmi-vector" "$FILE_WITH_NMI_VECTOR_TO_PROCESS" "$FILE_WITH_NMI_VECTOR_TO_PROCESS.no-nmi" >/dev/null 2>&1 else "$TOOLS_DIR/remove-nmi-vector" "$FILE_WITH_NMI_VECTOR_TO_PROCESS" "$FILE_WITH_NMI_VECTOR_TO_PROCESS.no-nmi" fi case "$?" in 0) mv -f "$FILE_WITH_NMI_VECTOR_TO_PROCESS.no-nmi" "$FILE_WITH_NMI_VECTOR_TO_PROCESS" ;; 1) warn2 "NMI vector not found. Assuming Freetz or Freetz-repacked image." ;; *) error 1 "fatal error while removing NMI vector from SquashFS." ;; esac fi "$TICHKSUM" -r "${KERNEL}" > /dev/null "$TICHKSUM" -r "${FIRMWARE_DIR}/${FILESYSTEM_IMAGE}" > /dev/null mkdir -p "$KERNEL_DIR" if [ "${FREETZ_AVM_HAS_SEPARATE_FILESYSTEM_IMAGE}" == "y" ]; then cp "${KERNEL}" "${RAW_KERNEL}" [ ! -r "$RAW_KERNEL" ] && error 1 "copying kernel image failed" if [ "${FREETZ_AVM_HAS_INNER_OUTER_FILESYSTEM}" == "y" ]; then echo "unpacking outer-filesystem image" modunpack_autodetect_fs "${FILESYSTEM_OUTER_DIR}" "${FIRMWARE_DIR}/${FILESYSTEM_IMAGE}" [ ! -r "$FILESYSTEM" ] && error 1 "unpacking outer-filesystem image failed" fi echo "unpacking ${INNER_FS_PREFIX}filesystem image" modunpack_autodetect_fs "$FILESYSTEM_DIR" "$FILESYSTEM" || error 1 "unpacking ${INNER_FS_PREFIX}filesystem image failed" else echo "splitting kernel image" ( cd "$KERNEL_DIR" && "${TOOLS_DIR}/${FINDSQUASHFS_TOOL}" "../${FIRMWARE_SUBDIR}/${KERNEL_IMAGE}" > /dev/null 2>&1 ) if [ ! -r "$RAW_KERNEL" -o ! -r "$FILESYSTEM" ]; then if [ -r "${FIRMWARE_DIR}/${FILESYSTEM_IMAGE}" ] && [ $(stat -c %s "${FIRMWARE_DIR}/${FILESYSTEM_IMAGE}") -gt 0 ]; then _config_hint=" - maybe you should configure a firmware with FREETZ_AVM_HAS_SEPARATE_FILESYSTEM_IMAGE/FREETZ_AVM_HAS_INNER_OUTER_FILESYSTEM" fi error 1 "kernel splitting failed${_config_hint}" fi echo "unpacking filesystem image" modunpack_autodetect_fs "$FILESYSTEM_DIR" "$FILESYSTEM" || error 1 "unpacking filesystem image failed" fi if [ -r "$AVMPLUGINS" ]; then echo0 "unpacking AVM plugins" mkdir -p "$AVMPLUGINS_DIR" "$TAR_GNU" -xif "$AVMPLUGINS" -C "$AVMPLUGINS_DIR" || error 1 "tar failed" for i in "${AVMPLUGINS_DIR}/var/"*.image; do AVMPLUGIN="${i##*/plugin-}" AVMPLUGIN="${AVMPLUGIN%\.image}" echo2 "$AVMPLUGIN image" modunpack_autodetect_fs "$AVMPLUGINS_DIR/plugin-${AVMPLUGIN}" "$i" > /dev/null done chmod -R +w "$AVMPLUGINS_DIR" fi if [ ! -r "$FILESYSTEM_DIR/var" ]; then error 1 "could not unpack the filesystem image" fi if [ ! -r "$VARTAR" ]; then error 1 "no var.tar found" fi echo "unpacking var.tar" mkdir "$VARTAR_DIR" "$TAR_GNU" -xipf "$VARTAR" -C "$VARTAR_DIR" || error 1 "tar failed" image_details echo2 -lc "detected firmware version: ${SOURCE_IMAGE_DETAILS}" echo -e "done.\n" # Unpack secondary firmware image if [ -n "$FIRMWARE2" ]; then rm -rf "${DIR}/.tk" # validate_signature [ $DO_VALIDATE2 -eq 1 ] && UNPACK_VALIDATE2="-v $FIRMWARE2_PUB" ( set -o pipefail; "$0" -u $UNPACK_VALIDATE2 -d "${DIR}/.tk" "$FIRMWARE2" | sed "s/STEP 1: UNPACK/STEP 1B: UNPACK 2ND${FORCE_UNPACK}/" ) [ $? -ne 0 ] && error 1 "unpacking failed" fi # Unpack auxiliary firmware image if [ -n "$FIRMWARE3" ]; then rm -rf "${DIR}/.aux" # validate_signature [ $DO_VALIDATE3 -eq 1 ] && UNPACK_VALIDATE3="-v $FIRMWARE3_PUB" ( set -o pipefail; "$0" -u $UNPACK_VALIDATE3 -d "${DIR}/.aux" "$FIRMWARE3" | sed "s/STEP 1: UNPACK/STEP 1C: UNPACK 3RD${FORCE_UNPACK}/" ) [ $? -ne 0 ] && error 1 "unpacking failed" fi # Create "unpacked" marker, recording exactly *what* was unpacked (MD5) echo "$FIRMWARE_MD5" > "$UNPACKED_FILE" fi echo0 -n -b "$SKIP_UNPACK" ############################################### # Lets copy and modify the unpacked firmware ## ############################################### # FREETZ_LIBRARY_DIR is the 1st FREETZ_RPATH entry FREETZ_LIBRARY_DIR=$(stripTrailingSlash "${FREETZ_RPATH%%:*}") MOD_DIR="${DIR}/modified" FIRMWARE_MOD_DIR="${MOD_DIR}/${FIRMWARE_SUBDIR}" FITIMAGE_MOD_DIR="${MOD_DIR}/${FITIMAGE_SUBDIR}" FILESYSTEM_MOD_DIR="${MOD_DIR}/${FILESYSTEM_SUBDIR}" FILESYSTEM_OUTER_MOD_DIR="${MOD_DIR}/${FILESYSTEM_OUTER_SUBDIR}" EXTERNAL_MOD_DIR="${MOD_DIR}/${EXTERNAL_SUBDIR}" KERNEL_MOD_DIR="${MOD_DIR}/${KERNEL_SUBDIR}" AVMPLUGINS_MOD_DIR="${KERNEL_MOD_DIR}/${AVMPLUGINS_SUBDIR}" AVMPLUGINS_FILESYSTEM_MOD_DIR="${FILESYSTEM_MOD_DIR}/usr/share/avmplugins" VARTAR_MOD_DIR="${KERNEL_MOD_DIR}/${VARTAR_SUBDIR}" KERNEL_MOD="${FIRMWARE_MOD_DIR}/${KERNEL_IMAGE}" FILESYSTEM_MOD="${FIRMWARE_MOD_DIR}/${FILESYSTEM_IMAGE}" RAW_KERNEL_MOD="${KERNEL_MOD_DIR}/${RAW_KERNEL_FILE}" RAW_FILESYSTEM_MOD="${KERNEL_MOD_DIR}/${RAW_HIDDEN_FILE}" if [ "${FREETZ_AVM_HAS_SEPARATE_FILESYSTEM_IMAGE}" == "y" ]; then if [ "${FREETZ_AVM_HAS_INNER_OUTER_FILESYSTEM}" == "y" ]; then MAIN_FILESYSTEM_MOD="${FILESYSTEM_OUTER_MOD_DIR}/${FILESYSTEM_INNER_IMAGE}" else MAIN_FILESYSTEM_MOD="$RAW_FILESYSTEM_MOD" fi else MAIN_FILESYSTEM_MOD="$RAW_FILESYSTEM_MOD" fi VARTAR_MOD="${FILESYSTEM_MOD_DIR}/${VARTAR_FILE}" [ "${FREETZ_SYSTEM_TYPE_BCM63138}" == "y" ] && TARGET_TOOLCHAIN_ID__GCC_SUFFIX="-bcm" [ "${FREETZ_AVM_UCLIBC_NPTL_ENABLED}" == "y" ] && TARGET_TOOLCHAIN_ID__UCLIBC_SUFFIX="-nptl" [ "${FREETZ_KERNEL_VERSION_3_10_MIN}" == "y" ] && TARGET_TOOLCHAIN_ID__KERNEL_SUFFIX="_kernel-${FREETZ_KERNEL_VERSION_MAJOR}" TARGET_TOOLCHAIN_ID="${FREETZ_TARGET_ARCH_ENDIANNESS_DEPENDENT}_gcc-${FREETZ_TARGET_GCC_VERSION}${TARGET_TOOLCHAIN_ID__GCC_SUFFIX}_uClibc-${FREETZ_TARGET_UCLIBC_VERSION}${TARGET_TOOLCHAIN_ID__UCLIBC_SUFFIX}${TARGET_TOOLCHAIN_ID__KERNEL_SUFFIX}" PACKAGES_DIR="${PACKAGES_DIR_ROOT}/target-${TARGET_TOOLCHAIN_ID}" TARGET_SPECIFIC_ROOT_DIR="${PACKAGES_DIR}/root" HTML_MOD_DIR="${FILESYSTEM_MOD_DIR}/${HTML_SUBDIR}" # $LUA_MOD_DIR can't be defined here. eg: ${FILESYSTEM_MOD_DIR}/usr/www/all/lua # $HTML_LANG_MOD_DIR can't be defined here. eg: ${FILESYSTEM_MOD_DIR}/usr/www/all # $HTML_SPEC_MOD_DIR can't be defined here. eg: ${FILESYSTEM_MOD_DIR}/usr/www/all/html/de # $MENU_DATA_LUA will be set below to ${FILESYSTEM_MOD_DIR}/usr/lua/menu_data.lua or ${HTML_LANG_MOD_DIR}/menus/menu_data.lua or filenotavailable # $SYSTEMD_CORE_MOD_DIR will be set below to ${FILESYSTEM_MOD_DIR}/etc/boot.d/core if it exists if [ -z "$FREETZ_SQUASHFS_BLOCKSIZE" ]; then # expected to be empty only if FREETZ_SQUASHFS_BLOCKSIZE_ORIG is set echo -n "determining SquashFS block size of the original firmware: " FREETZ_SQUASHFS_BLOCKSIZE=$("$UNSQUASHFS" -s "$FILESYSTEM" 2>/dev/null | sed -nr 's/Block size ([0-9]+)/\1/p') [ -z "$FREETZ_SQUASHFS_BLOCKSIZE" ] && error 1 "failed" || echo -e "$((FREETZ_SQUASHFS_BLOCKSIZE/1024)) kB\n" fi MKSQUASHFS_OPTIONS+=" -b $FREETZ_SQUASHFS_BLOCKSIZE" #echo "Using '$MKSQUASHFS_OPTIONS' as MKSQUASHFS_OPTIONS" if [ "$FREETZ_SIZEINFO_COMPRESSED" == "y" ]; then let FILESYSTEM_BLOCKSIZE_KB=$FREETZ_SQUASHFS_BLOCKSIZE/1024 SIZEINFO_CACHEDIR=${PACKAGES_DIR}/freetzcachedsizes mkdir -p ${SIZEINFO_CACHEDIR} fi function sizeinfo() { [ "$FREETZ_VERBOSITY_LEVEL" -lt 1 ] && return #formated output if [ $# -eq 1 ]; then if [ "$FREETZ_SIZEINFO_COMPRESSED" != "y" ]; then echo1 "$1" else echo1 -n "$(printf "%-34s " "${1:0:31}" | sed 's/ /\./g;s/\.\./ ./;s/\.(addon)/ (addon)/')" fi return fi [ "$FREETZ_SIZEINFO_COMPRESSED" != "y" ] && return #cache file local sizeinfo_mode=$1 shift case $sizeinfo_mode in lib) #libraries: multiple files local shash="$(ls -l $@ | sort | $MD5SUM)" local sfile="${SIZEINFO_CACHEDIR}/$(echo $@ | sed -rn 's!.*/(.*)\.so.*!\1!p').sizeinfo.MD5_${shash/ */}.BS_${FILESYSTEM_BLOCKSIZE_KB}" ;; mod) #modules: one .ko file local shash="$(ls -l $1 | $MD5SUM)" local sfile="${SIZEINFO_CACHEDIR}/${1##*/}.sizeinfo.MD5_${shash/ */}.BS_${FILESYSTEM_BLOCKSIZE_KB}" ;; pkg) #packages: files (without .excluded) local shash="$(echo $* | sort | $MD5SUM)" local sfile="${1}/.sizeinfo.MD5_${shash/ */}.BS_${FILESYSTEM_BLOCKSIZE_KB}" shift ;; dir) #addons/plugins: one directory local shash="$(find $1 -type f -exec ls -l {} ';' | $MD5SUM)" local sfile="${SIZEINFO_CACHEDIR}/${1##*/}.sizeinfo.MD5_${shash/ */}.BS_${FILESYSTEM_BLOCKSIZE_KB}" ;; *) echo "invalid" return ;; esac #compressed size if [ ! -s "$sfile" ]; then if [ $# -eq 0 ]; then echo -n " 0.00 kB (uncompressed: 0.00 kB)" > ${sfile} else local tempf=/tmp/freetz-sizeinfo-$$.tmp "$MKSQUASHFS" $@ $tempf $MKSQUASHFS_OPTIONS 2>/dev/null | grep -A1 ^Filesystem \ | sed -n 'N;s!Filesystem size \(.*\)ytes (.*\n.*(\(.*\)ytes.*$!\1 \2!p' \ | awk '{printf "%8s%3s (uncompressed:%8s%3s)",$1,$2,$3,$4}' > ${sfile} rm -rf $tempf 2>/dev/null fi fi #uncompressed size if [ "$FREETZ_SIZEINFO_UNCOMPRESSED" = "y" ]; then cat ${sfile} else cat ${sfile} | sed 's/(uncompressed.*//' fi echo } image_details STEP="2" if [ "$DO_MOD" -gt 0 ]; then echo0 -b "STEP 2: MODIFY" # Check if firmware is unpacked if [ ! -r "$UNPACKED_FILE" ]; then error 1 "firmware image has to be unpacked before modifying" fi rm -rf "$MOD_DIR" rm -f "${DIR}/.modified" # Copy the unpacked directory [ -n "$PV" ] && echo0 "preparing directory build/modified/" mkdir -p "$MOD_DIR" [ "$FREETZ_AVM_HAS_UDEV" == y ] || exclude_dev="--exclude=./filesystem/dev" "$TAR_GNU" -c -C "$ORG_DIR" $exclude_dev --exclude='*.log' . | ${PV:-cat} | "$TAR" -x -C "$MOD_DIR" || error 1 "tar failed" # Fix some permissions chmod -R u+w "$FILESYSTEM_MOD_DIR" find "${FILESYSTEM_MOD_DIR}" "${VARTAR_MOD_DIR}" -type d -exec chmod 755 {} '+' # Give all users write permissions to /var/tmp to allow it to be used as a temp-directory. # Set sticky bit to prevent users from deleting/renaming files they are not the owners of. # NB: The permissions set are the regular temp-directory permissions on Unix-like systems. chmod 1777 "${VARTAR_MOD_DIR}/var/tmp" # determine OEMs supported by the original firmware all_known_oems="1und1 aol avm avme ewetel freenet otwo tcom versatel" iterate_over_oems_pattern='for[ ]+i[ ]+in[ ]+('"${all_known_oems// /|}"')[^;]*;[ ]*do' oems=$(sed -n -r -e '/'"${iterate_over_oems_pattern}"'/ { s/^.*for[ ]+i[ ]+in[ ]+([^;]+);[ ]+do.*$/\1/p; q }' "${FIRMWARE_MOD_DIR}/var/install") [ -z "$oems" ] && for oem in ${FILESYSTEM_MOD_DIR}/etc/default.Fritz_Box_*/*; do oems="$oems ${oem##*/}"; done [ -z "$oems" ] && error 1 "failed to determine OEMs supported by the original firmware" echo0 -n "applying symlinks, deleting additional webinterfaces" echo1 -ln " in:" for webdir in \ ${FILESYSTEM_MOD_DIR}/usr/www \ ${FILESYSTEM_MOD_DIR}/usr/www.nas \ ${FILESYSTEM_MOD_DIR}/usr/www.myfritz \ ; do [ ! -d ${webdir} ] && continue for edition in ewetel; do [ ! -d ${webdir}/$edition ] && continue [ -d ${webdir}/avm ] && continue [ -d ${webdir}/all ] && continue # force creation of /usr/www/all/ mv ${webdir}/$edition ${webdir}/avm done # some recent LTE firmwares contain both avm and avme OEMs (identical in all firmwares seen so far) # use the 1st of them (according to the alphabetical order) as the main one main_oem=$(find "${webdir}" -maxdepth 1 -type d -name "avm*" -printf "%P\n" | sort | head -n 1) if [ -n "${main_oem}" ]; then echo1 -ln " ${webdir#${FILESYSTEM_MOD_DIR}/}" mv ${webdir}/${main_oem} ${webdir}/all for i in $oems; do rm -rf ${webdir}/$i ln -s all ${webdir}/$i done fi done echo0 echo0 "applying patches" # Include patching helper function (modpatch) source "${TOOLS_DIR}/freetz_patch" || error 1 "cannot find script freetz_patch" PATCHES_DEVICES_DIR_FW_SERIES_SPECIFIC="${PATCHES_DEVICES_DIR}/${FREETZ_TYPE_PREFIX_SERIES_SUBDIR}" PATCHES_DEVICES_DIR_BOX_SPECIFIC="${PATCHES_DEVICES_DIR_FW_SERIES_SPECIFIC}/${FREETZ_TYPE_PREFIX%_*}" declare -a PATCHES_DEVICES_DIR_FULL_LIST=($( for j in \ ${PATCHES_DEVICES_DIR_FW_SERIES_SPECIFIC} \ ${PATCHES_DEVICES_DIR_BOX_SPECIFIC} \ $( [ -n "${FREETZ_TYPE_PREFIX_LABOR_FIRMWARE}" ] && echo "${PATCHES_DEVICES_DIR_BOX_SPECIFIC}/${FREETZ_TYPE_PREFIX_LABOR_FIRMWARE:1}" ) \ ; do for i in $j $j/${FREETZ_TYPE_LANGUAGE}; do echo "${i}" done done )) # Apply patches if [ -d "$FREETZ_TYPE_PREFIX_SERIES_SUBDIR" ]; then echo1 "applying patches: ${FREETZ_TYPE_PREFIX_SERIES_SUBDIR}/${FREETZ_TYPE_PREFIX}${FREETZ_TYPE_PREFIX_LABOR_FIRMWARE}-${FREETZ_TYPE_LANGUAGE} (${PATCHES_DEVICES_DIR_FULL_LIST[@]#${PATCHES_DEVICES_DIR}/})" fi # Execute firmware-series-specific and box-specific patch scripts (both common for all languages and language-specific) shopt -s nullglob for j in ${PATCHES_DEVICES_DIR_FULL_LIST[@]}; do for i in $j/*.sh; do echo2 "applying patch file $i" source $i done done shopt -u nullglob # Now we are in place to check html directory for i in all/en all ewetel; do if [ -d "${HTML_MOD_DIR}/$i" ]; then HTML_LANG_MOD_DIR="${HTML_MOD_DIR}/$i" break fi done # Find menu_data.lua MENU_DATA_LUA="filenotavailable" for dir in "${FILESYSTEM_MOD_DIR}/usr/lua" "${HTML_LANG_MOD_DIR}/menus"; do [ -f "$dir/menu_data.lua" ] && MENU_DATA_LUA="$dir/menu_data.lua" && break done # Check systemd direcotry [ -d "${FILESYSTEM_MOD_DIR}/etc/boot.d/core" ] && SYSTEMD_CORE_MOD_DIR="${FILESYSTEM_MOD_DIR}/etc/boot.d/core" || SYSTEMD_CORE_MOD_DIR="" # Now check language specific html directory (if there is any) for i in de en; do if [ -d "${HTML_LANG_MOD_DIR}/html/$i" ]; then HTML_SPEC_MOD_DIR="${HTML_LANG_MOD_DIR}/html/$i" break fi done echo1 "Language specific HTML directory: ${HTML_SPEC_MOD_DIR:-none}" if [ -z "$HTML_SPEC_MOD_DIR" ]; then HTML_SPEC_MOD_DIR="${HTML_LANG_MOD_DIR}/html/doesnotexist" FREETZ_AVM_HAS_ONLY_LUA=y [ "$FREETZ_AVM_VERSION_07_0X_MIN" == "y" -o -e "${FILESYSTEM_MOD_DIR}/usr/www/all/css/rd/images/fritzLogo.svg" ] && FREETZ_AVM_HAS_LUA_SCALABLE=y fi # Check for LUA directory LUA_MOD_DIR="${FILESYSTEM_MOD_DIR}/usr/lua" [ -d "$LUA_MOD_DIR" ] || LUA_MOD_DIR="${HTML_LANG_MOD_DIR}/lua" [ -d "$LUA_MOD_DIR" ] && echo1 "LUA directory: ${LUA_MOD_DIR}" || FREETZ_AVM_HAS_ONLY_HTML=y # Determine $MODULES_DIR in AVM image, eg: "${FILESYSTEM_MOD_DIR}/lib/modules/2.6.19.2 MODULES_DIR="$(find ${FILESYSTEM_MOD_DIR}/lib/modules/[2345].[0123456789]*.* -maxdepth 0 -type d 2>/dev/null)" [ ! -d "$MODULES_DIR" ] && error 1 "Cannot find modules dir." # Set $MODULES_SUBDIR relative to root dir in AVM image, eg: "lib/modules/2.6.19.2 MODULES_SUBDIR="${MODULES_DIR#${FILESYSTEM_MOD_DIR}/}" # Apply firmware-series-specific and box-specific patches (both common for all languages and language-specific) shopt -s nullglob for ((j=0; j<${#PATCHES_DEVICES_DIR_FULL_LIST[@]}; j++)); do for i in ${PATCHES_DEVICES_DIR_FULL_LIST[$j]}/*.patch; do # Check if a more specific version of the patch exists, # i.e. define an order on all patches with the same name # FW_SERIES/XY.patch # FW_SERIES/LANG/XY.patch # FW_SERIES/BOXID/XY.patch # FW_SERIES/BOXID/LANG/XY.patch # and do NOT apply patch XY.patch from dir FOO # if it also exists in a directory with a higher order. # # This makes it possible in situations where one box needs # a box-specific version of the patch to have just two versions # of it: one box-specific and one for all other boxes. i_basename=$(basename "$i") for ((jj=j+1; jj<${#PATCHES_DEVICES_DIR_FULL_LIST[@]}; jj++)); do if [ -f "${PATCHES_DEVICES_DIR_FULL_LIST[$jj]}/${i_basename}" ]; then continue 2 fi done modpatch "$FILESYSTEM_MOD_DIR" "$i" done done shopt -u nullglob echo1 "creating symlinks /tmp, /mod, /home and /ftp" rm -rf "$FILESYSTEM_MOD_DIR"/tmp ln -s var/{tmp,mod} "$FILESYSTEM_MOD_DIR"/ ln -s var/mod/home "$FILESYSTEM_MOD_DIR"/ ln -s var/media/ftp "$FILESYSTEM_MOD_DIR"/ echo1 "creating /mnt and /opt" mkdir -p "$FILESYSTEM_MOD_DIR"/mnt # 7390: /opt is symlink to /var/InternerSpeicher/opt [ ! -L "$FILESYSTEM_MOD_DIR"/opt ] && mkdir -p "$FILESYSTEM_MOD_DIR"/opt # Determine Freetz version FREETZ_VERSION="$(${TOOLS_DIR}/freetz_revision fwmod)" echo1 "setting freetz-version '${FREETZ_VERSION}'" echo "${FREETZ_VERSION}" > "${FILESYSTEM_MOD_DIR}/etc/.freetz-version" ln -f "${FILESYSTEM_MOD_DIR}/etc/.freetz-version" "${FILESYSTEM_MOD_DIR}/etc/.freetz-ng-version" # Execute general patch scripts for i in "${PATCHES_SCRIPTS_DIR}/"*.sh; do [ -r "$i" ] || continue echo2 -l "applying patch file $i" source $i done # stop execution if in patch test mode if [ "$FWMOD_PATCH_TEST" == "y" ]; then echo0 -b "Patch test mode: exiting without error." exit fi echo1 -l "patches applied" # remove oems echo1 -ln "removing oem:" oem_removed=0 oem_kept=0 oem_list= ln -sf /usr/www/cgi-bin/freetz_status "${HTML_LANG_MOD_DIR}/cgi-bin/freetz_status" for i in $oems; do if [ "$(eval "echo \"\$FREETZ_REMOVE_BRANDING_${i}\"")" == "y" ]; then echo1 -ln " $i" # delete webinterface symlinks otherwise user can choose branding in status.cgi rm -rf "${FILESYSTEM_MOD_DIR}/usr/www/${i}" rm -rf "${FILESYSTEM_MOD_DIR}/usr/www.nas/${i}" rm -rf "${FILESYSTEM_MOD_DIR}/usr/www.myfritz/${i}" find ${FILESYSTEM_MOD_DIR}/etc/default.* -name "*${i}*" | xargs rm -rf oem_removed=1 else oem_list+=" $i" oem_kept=1 fi done [ "$oem_removed" -eq 0 ] && echo1 -ln " none" echo1 -l if isFreetzType W501V; then oem_list="tcom avm" fi sed -i -r -e 's/'"${iterate_over_oems_pattern}"'/for i in '"$oem_list"' ; do/' "${FIRMWARE_MOD_DIR}/var/install" if [ "$oem_kept" -eq 0 ]; then error 1 "please choose at least one OEM (branding) in menuconfig: AVM, 1&1, Freenet etc." fi # Copy selected avmplugins to the firmware if [ "$FREETZ_AVMPLUGINS_INTEGRATE" == "y" ]; then echo0 "integrating AVM plugins" echo "#" > ${FILESYSTEM_MOD_DIR}/sbin/start_plugin.sh rm -rf ${FIRMWARE_MOD_DIR}/${AVMPLUGINS_FILE} mkdir "${AVMPLUGINS_FILESYSTEM_MOD_DIR}" for i in `find "${AVMPLUGINS_MOD_DIR}" -maxdepth 1 -type d -name var -prune -false , -type d -name "plugin-*" 2>/dev/null`; do AVMPLUGIN="${i##*plugin-}" if [ "$(eval "echo \"\$FREETZ_AVMPLUGINS_$(echo "$AVMPLUGIN" | tr '[:lower:]' '[:upper:]')\"")" == "y" ]; then sizeinfo "$AVMPLUGIN" sizeinfo dir "$i" cp -a "${AVMPLUGINS_MOD_DIR}/plugin-${AVMPLUGIN}" "${AVMPLUGINS_FILESYSTEM_MOD_DIR}/plugin-${AVMPLUGIN}" ln -s "/usr/share/avmplugins/plugin-${AVMPLUGIN}" "${VARTAR_MOD_DIR}/var/plugin-${AVMPLUGIN}" for module in `cd "${AVMPLUGINS_FILESYSTEM_MOD_DIR}/plugin-${AVMPLUGIN}";find -type f -name "*.ko"`; do echo2 "moving to standard modules dir: ${module##*/}" mv "${AVMPLUGINS_FILESYSTEM_MOD_DIR}/plugin-${AVMPLUGIN}/$module" "${FILESYSTEM_MOD_DIR}/$module" done case "$AVMPLUGIN" in tam) modsed \ "s/ CONFIG_TAM_ONRAM=.*$/ CONFIG_TAM_ONRAM=\"n\"/g" \ "${FILESYSTEM_MOD_DIR}/etc/init.d/rc.conf" ;; wlan) modsed -r \ 's,(if) (.+ plugin-wlan),\1 test -d "/usr/share/avmplugins/plugin-wlan" || \2,' \ "${FILESYSTEM_MOD_DIR}/etc/init.d/rc.wlan" ;; esac fi done fi if [ "$FREETZ_INSTALL_BASE" == "y" ]; then echo0 "installing mod base" MOD_ROOT="${VARTAR_MOD_DIR}/var/mod" mkdir -p "${MOD_ROOT}/pkg" "${MOD_ROOT}/home" "${MOD_ROOT}/lib" "${MOD_ROOT}/root" mkdir -p "${MOD_ROOT}/bin" "${MOD_ROOT}/sbin" mkdir -p "${MOD_ROOT}/var/cache" mkdir -p "${MOD_ROOT}/var/spool/cron/crontabs" mkdir -p "${MOD_ROOT}/usr/bin" "${MOD_ROOT}/usr/sbin" "${MOD_ROOT}/usr/share" \ "${MOD_ROOT}/usr/lib" "${MOD_ROOT}/usr/lib/cgi-bin" "${MOD_ROOT}${FREETZ_LIBRARY_DIR}" mkdir -p "${MOD_ROOT}/etc/conf" "${MOD_ROOT}/etc/init.d" "${MOD_ROOT}/etc/reg" ln -s /tmp/flash/mod/.profile "${MOD_ROOT}/root/.profile" # AVM compatibility symlink ln -s ../sys "${VARTAR_MOD_DIR}/var/sysfs" grep -q '^root:' "${VARTAR_MOD_DIR}/var/tmp/passwd" 2>/dev/null && \ sed 's,^root:.*,root:x:0:0:root:/mod/root:/bin/sh,' -i "${VARTAR_MOD_DIR}/var/tmp/passwd" || \ echo "root:x:0:0:root:/mod/root:/bin/sh" >> "${VARTAR_MOD_DIR}/var/tmp/passwd" grep -q '^root:' "${VARTAR_MOD_DIR}/var/tmp/shadow" 2>/dev/null && \ sed 's,^root:.*,root:$1$$zO6d3zi9DefdWLMB.OHaO.:12332:0:99999:7:::,' -i "${VARTAR_MOD_DIR}/var/tmp/shadow" || \ echo 'root:$1$$zO6d3zi9DefdWLMB.OHaO.:12332:0:99999:7:::' >> "${VARTAR_MOD_DIR}/var/tmp/shadow" grep -q '^root:' "${VARTAR_MOD_DIR}/var/tmp/group" 2>/dev/null && \ sed 's,^root:.*,root:x:0:,' -i "${VARTAR_MOD_DIR}/var/tmp/group" || \ echo "root:x:0:" >> "${VARTAR_MOD_DIR}/var/tmp/group" grep -q '^users:' "${VARTAR_MOD_DIR}/var/tmp/group" 2>/dev/null && \ sed 's,^users:.*,root:x:0:,' -i "${VARTAR_MOD_DIR}/var/tmp/group" || \ echo "users:x:80:" >> "${VARTAR_MOD_DIR}/var/tmp/group" touch "${VARTAR_MOD_DIR}/var/tmp/ethers" touch "${VARTAR_MOD_DIR}/var/tmp/exports" touch "${VARTAR_MOD_DIR}/var/tmp/gshadow" chmod 644 "${VARTAR_MOD_DIR}/var/tmp/passwd" "${VARTAR_MOD_DIR}/var/tmp/group" chmod 600 "${VARTAR_MOD_DIR}/var/tmp/shadow" "${VARTAR_MOD_DIR}/var/tmp/gshadow" # Fix permissions set by AVM, in particular revoke write permissions for g- and o-users. chmod 644 "${VARTAR_MOD_DIR}/var/tmp/hosts" "${VARTAR_MOD_DIR}/var/tmp/resolv.conf" mkdir -p "${VARTAR_MOD_DIR}/var/tmp/onlinechanged" mkdir -p "${VARTAR_MOD_DIR}/var/mod/etc/onlinechanged" mkdir -p "${VARTAR_MOD_DIR}/var/mod/etc/cron.d" ln -s ../var/tmp/ethers "${FILESYSTEM_MOD_DIR}/etc/ethers" ln -s ../var/tmp/exports "${FILESYSTEM_MOD_DIR}/etc/exports" ln -s ../var/tmp/gshadow "${FILESYSTEM_MOD_DIR}/etc/gshadow" rm -f ${VARTAR_MOD_DIR}/var/*/.dummy echo0 "installing libs" for i in $(set | grep ^FREETZ_LIB_.*=y | grep -v ^FREETZ_LIB_STDCXXLIB); do all_files="" found=0 conf=${i%%=*} [ "$conf" != "${conf%%_WITH_*}" ] && continue # skip suboptions [ "$conf" != "${conf%%_VERSION_*}" ] && continue # skip version bn=${conf#FREETZ_LIB_} if [ "$FREETZ_KEEP_AVM_UCLIBC" == "y" ]; then # libutil is actually also a uClibc lib, but it's not provided by AVM, so keep installing Freetz version if echo "${bn}" | grep -qE '^(ld_uClibc|libcrypt|libdl|libm|libpthread|librt|libthread_db|libubacktrace|libuClibc)$'; then echo1 "keeping AVM version of uClibc library $bn" continue fi fi fn=${bn//_/[-+._]} sizeinfo "$bn" [ "$FREETZ_SEPARATE_AVM_UCLIBC" == "y" ] \ && LIBPATHS="${FREETZ_LIBRARY_DIR#/} lib usr/lib usr/lib/xtables" \ || LIBPATHS="lib usr/lib ${FREETZ_LIBRARY_DIR#/} usr/lib/xtables" for dn in $LIBPATHS; do files=$(shopt -s nullglob; echo ${TARGET_SPECIFIC_ROOT_DIR}/$dn/$fn[-.]*so*) if [ -z "$files" ]; then continue; fi found=1 [ -d "${FILESYSTEM_MOD_DIR}/${dn}" ] || mkdir -p "${FILESYSTEM_MOD_DIR}/${dn}" cp -a $files "${FILESYSTEM_MOD_DIR}/${dn}/" if [ "${FREETZ_AVM_HAS_INNER_OUTER_FILESYSTEM}" == "y" -a "$FREETZ_REPLACE_OUTER_UCLIBC_AND_BUSYBOX" == "y" ]; then wrapper_fs_required_libs="ld_uClibc libuClibc" # replaced busybox might require some additional libraries not available in AVM's wrapper filesystem [ "$FREETZ_REPLACE_BUSYBOX" == "y" -a -r "${PACKAGES_DIR}/busybox/busybox" ] && \ wrapper_fs_required_libs+=" $(getNeededEntries ${PACKAGES_DIR}/busybox/busybox | sed -r -e 's,[.]so([.].+)?$,,' | sort | tr $'\n' " ")" if echo "${bn}" | grep -qE "^($(join '|' ${wrapper_fs_required_libs}))$"; then cp -a $files "${FILESYSTEM_OUTER_MOD_DIR}/${dn}/" fi fi all_files="$all_files $files" done if [ "$found" = 0 ]; then warn "Library $bn selected, but no files found" else sizeinfo lib "$all_files" fi done if [ "$FREETZ_KEEP_AVM_UCLIBC" != "y" -a "$FREETZ_LIB_libuClibc" == "y" ]; then [ "$FREETZ_SEPARATE_AVM_UCLIBC" == "y" ] && \ cp -a ${TARGET_SPECIFIC_ROOT_DIR}${FREETZ_LIBRARY_DIR}/libc.so.? "${FILESYSTEM_MOD_DIR}${FREETZ_LIBRARY_DIR}/" || \ cp -a "${TARGET_SPECIFIC_ROOT_DIR}/lib/libc.so.${FREETZ_TARGET_UCLIBC_MAJOR_VERSION}" "${FILESYSTEM_MOD_DIR}/lib/" [ "${FREETZ_AVM_HAS_INNER_OUTER_FILESYSTEM}" == "y" -a "$FREETZ_REPLACE_OUTER_UCLIBC_AND_BUSYBOX" == "y" ] && \ cp -a "${TARGET_SPECIFIC_ROOT_DIR}/lib/libc.so.${FREETZ_TARGET_UCLIBC_MAJOR_VERSION}" "${FILESYSTEM_OUTER_MOD_DIR}/lib/" fi echo1 "checking OpenSSL version" DETECTED_OPENSSL_VER_AVM="$(find ${FILESYSTEM_DIR}/lib/libcrypto.so.* -type f -exec strings {} \; 2>/dev/null | sed -nr 's/^@?OpenSSL ([0-9]\.[-0-9a-z\.]*)[ \t]*/\1\t/p')" echo2 "... used by AVM ...... ${DETECTED_OPENSSL_VER_AVM:-none}" if [ "$FREETZ_LIB_libcrypto" == "y" ]; then DETECTED_OPENSSL_VER_MOD="$(find ${FILESYSTEM_MOD_DIR}${FREETZ_LIBRARY_DIR}/libcrypto.so.* -type f -exec strings {} \; | sed -nr 's/^@?OpenSSL ([0-9]\.[-0-9a-z\.]*)[ \t]*/\1\t/p')" echo2 "... used by Freetz ... ${DETECTED_OPENSSL_VER_MOD:-none}" # [ "$DETECTED_OPENSSL_VER_MOD" != "$DETECTED_OPENSSL_VER_AVM" ] & warn2 "Freetz and AVM OpenSSL versions do not match" fi unset DETECTED_OPENSSL_VER_AVM unset DETECTED_OPENSSL_VER_MOD echo1 "checking libc version" DETECTED_UCLIBC_VER="$(readlink ${FILESYSTEM_DIR}/lib/libc.so.? | sed 's/\.so$//;s/^libc/g&/;s/^lib//;s/-/ /' | head -n1)" [ -z "$DETECTED_UCLIBC_VER" ] && [ -n "$(strings ${FILESYSTEM_DIR}/lib/libc.so | grep '^musl libc')" ] && \ DETECTED_UCLIBC_VER="musl $(strings ${FILESYSTEM_DIR}/lib/libc.so | grep '^[0-1]\.[0-9]\.[0-9][0-9]*$')" echo2 "... used by AVM ...... $DETECTED_UCLIBC_VER" echo2 "... used by Freetz ... uClibc ${FREETZ_TARGET_UCLIBC_VERSION}" if [ "${FREETZ_TARGET_UCLIBC_VERSION#${DETECTED_UCLIBC_VER#uClibc }}" == "$FREETZ_TARGET_UCLIBC_VERSION" -a "${FREETZ_SEPARATE_AVM_UCLIBC}" != "y" ]; then warn2 "Freetz and AVM uClibc versions do not match" fi unset DETECTED_UCLIBC_VER if [ "$FREETZ_SHARE_terminfo" == "y" ]; then echo1 "installing terminfos" for i in $(set | grep ^FREETZ_SHARE_terminfo_.*=y |grep -v '^FREETZ_SHARE_terminfo_showall=' ); do dn=usr/share/terminfo conf=${i%%=*} bn=${conf#FREETZ_SHARE_terminfo_} fn=$(echo "$bn" | sed 's/MINUS/-/g;s/PLUS/+/g;s/\DOT/./g') echo2 "$fn" fn="${fn:0:1}/$fn" file="${TARGET_SPECIFIC_ROOT_DIR}/$dn/$fn" if [ ! -e "$file" ]; then warn "Terminfo $bn selected, but no file found" continue; fi dest="${FILESYSTEM_MOD_DIR}/$dn/${fn:0:1}" [ -d "$dest" ] || mkdir -p "$dest" cp -a $file "$dest/" done fi else error 1 "installation of base system is mandatory" fi if [ "$FIRMWARE_NOCOMPILE" != "1" ]; then [ "$FREETZ_REPLACE_BUSYBOX" != "y" ] && error 1 "installation of busybox replacement is mandatory" echo0 "installing busybox" [ "$FREETZ_BUSYBOX__ADDITIONAL" == "y" ] && BBBIN='busybox-freetz' || BBBIN='busybox' DIRS_BUSYBOX_TO_REPLACE_WITHIN="${FILESYSTEM_MOD_DIR}" [ "${FREETZ_AVM_HAS_INNER_OUTER_FILESYSTEM}" == "y" -a "$FREETZ_REPLACE_OUTER_UCLIBC_AND_BUSYBOX" == "y" ] && DIRS_BUSYBOX_TO_REPLACE_WITHIN+=" ${FILESYSTEM_OUTER_MOD_DIR}" echo1 "replacing busybox" [ ! -r "${PACKAGES_DIR}/busybox/busybox" ] && error 1 "cannot find busybox replacement" for d in ${DIRS_BUSYBOX_TO_REPLACE_WITHIN}; do cp -pf "${PACKAGES_DIR}/busybox/busybox" "${d}/bin/$BBBIN"; done echo1 "installing symlinks" [ ! -r "${PACKAGES_DIR}/busybox/busybox.links" ] && error 1 "cannot find busybox links" # check avm's busybox links to warn about missing freetz applets # this does not detect applets without links, like netcat, tcpsvd & timeout MISSING_APPLETS="n" find ${DIRS_BUSYBOX_TO_REPLACE_WITHIN} \( -lname "busybox" -or -lname "*/busybox" \) -exec basename {} ';' | sort -u | \ while read -r LINK_NAME; do grep -q "/${LINK_NAME//[/\\[}$" "${PACKAGES_DIR}/busybox/busybox.links" && continue echo2 -bc "missing applet detected: $LINK_NAME" MISSING_APPLETS="y" done [ "$MISSING_APPLETS" != "n" ] && error 1 "busybox failed" # ### Disabled as in case of non default location and hardcoded path by avm # # Remove old busybox links # # be compatible: do not use -delete (not found in older versions of find) # find ${DIRS_BUSYBOX_TO_REPLACE_WITHIN} \( -lname "$BBBIN" -or -lname "*/$BBBIN" \) -print0 | xargs -0r rm # Install new busybox links - sorted by applet name for link in $(cat "${PACKAGES_DIR}/busybox/busybox.links" | sed -nr 's,(.*)/(.*)$,\2 \1,p'|sort|sed -nr 's,(.*) (.*),\2/\1,p'); do LINK_DIR="$(dirname "$link")" LINK_NAME="$(basename "$link")" case "$LINK_DIR" in /) BUSYBOX_PATH="bin/$BBBIN" ;; /bin) BUSYBOX_PATH="$BBBIN" ;; /sbin) BUSYBOX_PATH="../bin/$BBBIN" ;; /usr/bin|/usr/sbin) BUSYBOX_PATH="../../bin/$BBBIN" ;; *) error 1 "unknown installation directory: $link" ;; esac for d in ${DIRS_BUSYBOX_TO_REPLACE_WITHIN}; do mkdir -p "${d}${LINK_DIR}" if [ -L "${d}${LINK_DIR}/$LINK_NAME" ]; then if [ "$FREETZ_BUSYBOX__ADDITIONAL" == "y" ]; then echo2 "additional -freetz link: $LINK_NAME" LINK_NAME="${LINK_NAME}-freetz" fi elif [ -f "${d}${LINK_DIR}/$LINK_NAME" ]; then if [ "$FREETZ_BUSYBOX__KEEP_BINARIES" != "y" ]; then echo2 "overwriting binary file: $LINK_NAME" else echo2 "renamed -busybox applet: $LINK_NAME" LINK_NAME="${LINK_NAME}-busybox" fi fi ln -sf "$BUSYBOX_PATH" "${d}${LINK_DIR}/$LINK_NAME" || error 1 "could not create link for $link" done done || error 1 "busybox failed" echo1 "checking BusyBox version" echo2 "... used by AVM ...... $(strings ${FILESYSTEM_DIR}/bin/busybox | sed 's/ ()//g' | sed -n 's/^BusyBox v//p')" echo2 "... used by Freetz ... $(strings ${FILESYSTEM_MOD_DIR}/bin/$BBBIN | sed -n 's/^BusyBox v//p')" fi echo0 "installing packages" for pkg in $(static_packages); do sizeinfo "$pkg" pkg_name=$(pkg_name "$pkg") "$TAR_GNU" $(find "${PACKAGES_DIR}/${pkg}/" -maxdepth 1 -type f -name ".exclude*" -printf '--exclude-from=%p ') \ -c -C "${PACKAGES_DIR}/${pkg}/root" . | "$TAR" -x -C "$FILESYSTEM_MOD_DIR" || error 1 "tar failed" if [ -d "${PACKAGES_DIR}/${pkg}/${VARTAR_SUBDIR}" ]; then "$TAR_GNU" -c -C "${PACKAGES_DIR}/${pkg}/${VARTAR_SUBDIR}" . | "$TAR" -x -C ${VARTAR_MOD_DIR} || error 1 "tar failed" fi [ -r "${PACKAGES_DIR}/${pkg}/.language" ] && \ modlang "${PACKAGES_DIR}/${pkg}/.language" "${FILESYSTEM_MOD_DIR}" if ! grep -q "^$pkg_name$" "${VARTAR_MOD_DIR}/var/mod/etc/static.pkg" >/dev/null 2>&1; then echo "$pkg_name" >> "${VARTAR_MOD_DIR}/var/mod/etc/static.pkg" fi pkgfiles=$(collect_pkg_files "${pkg}" | sed -e "s,^,${PACKAGES_DIR}/${pkg}/root,") sizeinfo pkg "${PACKAGES_DIR}/${pkg}" $pkgfiles done # order pkg-short package version symbol sort "$PACKAGES_LIST_FILE" | while read sxx pkg ver xxx; do echo "$sxx $(pkg_name $pkg-$ver) $pkg ${ver:0:12} $xxx" done > "${VARTAR_MOD_DIR}/var/mod/etc/packages.lst" [ -n "$(static_addons)" ] && echo0 "installing addons" for pkg in $(static_addons); do sizeinfo "$pkg" [ ! -d "${ADDON_DIR}/${pkg}" ] && error 1 "can not find addon directory" pkg_name=$(pkg_name "$pkg") if [ -e "${ADDON_DIR}/${pkg}/etc/init.d/rc.${pkg_name}" ]; then echo "NOTICE: addon '$pkg' is in old-style format (no language support)." 1>&2 "$TAR_GNU" -c -C "${ADDON_DIR}/${pkg}" . | "$TAR" -x -C "$FILESYSTEM_MOD_DIR" || error 1 "tar failed" elif [ "$(echo ${pkg^^}-corrupt | sed -r 's/([^.-_-]*).*/\LfLawed-\1-Addon/' | md5sum | sed 's/ .*//')" != "80d00cf16e1a48ec11801feed60a2be7" ]; then "$TAR" $(find "${ADDON_DIR}/${pkg}/" -maxdepth 1 -type f -name ".exclude*" -printf '--exclude-from=%p ') \ -c -C "${ADDON_DIR}/${pkg}/root" \ . | \ "$TAR" -x -C "$FILESYSTEM_MOD_DIR" || error 1 "tar failed" if [ -d "${ADDON_DIR}/${pkg}/${VARTAR_SUBDIR}" ]; then "$TAR_GNU" -c -C "${ADDON_DIR}/${pkg}/${VARTAR_SUBDIR}" . | "$TAR" -x -C ${VARTAR_MOD_DIR} || error 1 "tar failed" fi [ -r "${ADDON_DIR}/${pkg}/.language" ] && \ modlang "${ADDON_DIR}/${pkg}/.language" "${FILESYSTEM_MOD_DIR}" fi if ! grep -q "^$pkg_name$" "${VARTAR_MOD_DIR}/var/mod/etc/static.pkg" >/dev/null 2>&1; then echo "$pkg_name" >> "${VARTAR_MOD_DIR}/var/mod/etc/static.pkg" fi rpn="$(real_pkg_name $pkg)" cfs="FREETZ_ADDON_${rpn//-/_}" echo "SXX $(pkg_name $pkg) $rpn ${pkg#$rpn-} ${cfs^^}" >> "${VARTAR_MOD_DIR}/var/mod/etc/packages.lst" sizeinfo dir "${ADDON_DIR}/${pkg}" done if [ "$FREETZ_AVM_HAS_USB_HOST" == "y" ]; then echo1 "checking blkid tools" blkids=0 [ "$FREETZ_AVM_HAS_E2FSPROGS" == "y" -a "$FREETZ_REMOVE_AVM_E2FSPROGS" != "y" ] && blkids=$((blkids+1)) && echo2 "... binary by avm" [ "$FREETZ_PACKAGE_FSTYP" == "y" ] && blkids=$((blkids+1)) && echo2 "... package fstype" [ "$FREETZ_PACKAGE_E2FSPROGS" == "y" -a "$FREETZ_PACKAGE_E2FSPROGS_BLKID" == "y" ] && blkids=$((blkids+1)) && echo2 "... package e2fsprogs" [ "$FREETZ_PACKAGE_UTIL_LINUX" == "y" ] && blkids=$((blkids+1)) && echo2 "... package util-linux" [ "$(eval echo "\$FREETZ_BUSYBOX___V$(echo ${FREETZ_BUSYBOX__VERSION_STRING/.} | head -c3)_BLKID")" == "y" ] && blkids=$((blkids+1)) && echo2 "... busybox applet" [ "$blkids" -gt 1 ] && echo1 " there are $blkids blkid tools installed" [ "$blkids" -eq 0 ] && warn1 "no blkid tool installed, automatic mounting may not work" fi KERNEL_ID="${FREETZ_SYSTEM_TYPE}${FREETZ_SYSTEM_TYPE_CORE_SUFFIX}-${FREETZ_AVM_SOURCE_ID}" if [ "$NOCOMPILE" != "1" -a "$FREETZ_REPLACE_KERNEL" == "y" ]; then echo0 "replacing kernel" if [ ! -r "${KERNEL_REP_DIR}/kernel-${KERNEL_ID}.bin" ]; then error 1 "can't find kernel for ref ${KERNEL_ID}" fi echo1 "replacing kernel-${KERNEL_ID}" cp "${KERNEL_REP_DIR}/kernel-${KERNEL_ID}.bin" "$RAW_KERNEL_MOD" fi # modules directory / correctly configured kernel version echo0 "processing kernel" echo1 "checking kernel version" echo2 "... used by AVM ...... ${MODULES_SUBDIR##*/}" echo2 "... used by Freetz ... ${FREETZ_KERNEL_VERSION_MODULES_SUBDIR}" if [ "lib/modules/${FREETZ_KERNEL_VERSION_MODULES_SUBDIR}" != "$MODULES_SUBDIR" ]; then if [ "$FREETZ_REPLACE_MODULE_AVAILABLE" == "y" ]; then error 1 "Freetz and AVM kernel versions do not match. Wrong kernel version configuration in Freetz?" else warn2 "Freetz and AVM kernel versions do not match. Wrong kernel version\nconfiguration in Freetz or no sources matching firmware version provided by AVM?" fi fi if [ "$FREETZ_REPLACE_KERNEL" == "y" -o -n "$(set|grep ^FREETZ_MODULE_.*=y)" -o -n "$FREETZ_MODULES_OWN" ]; then [ "$FREETZ_STRIP_MODULES_FREETZ" == "y" ] && strip_output=" and stripping" echo0 "installing$strip_output modules" for i in \ $( \ cd "${KERNEL_REP_DIR}/modules-${KERNEL_ID}" && \ find . -type f \( -name modules.dep -o -name "*.ko" \) \ ); do bn="$(basename "$i")" ko_symbol="$(echo "${bn%\.ko}" | tr '\-+' '_x')" ko_install="$(eval "echo \"\$FREETZ_MODULE_$ko_symbol\"")" echo " $FREETZ_MODULES_OWN " | grep -q " $ko_symbol " && ko_install="y" [ "$FREETZ_MODULES_ALL" = "y" -o "$ko_install" == "y" ] || continue sizeinfo "$bn" ko_file_src="${KERNEL_REP_DIR}/modules-${KERNEL_ID}/${i}" ko_path_dst="${MODULES_DIR}/kernel/$(dirname "$i")" [ -d "$ko_path_dst" ] || mkdir -p "$ko_path_dst" cp -a $ko_file_src "$ko_path_dst/" if [ "$FREETZ_STRIP_MODULES_FREETZ" == "y" ]; then ${ABS_BASE_DIR}/toolchain/kernel/bin/${FREETZ_KERNEL_CROSS}strip -p --strip-unneeded \ --remove-section={.comment,.pdr,.mdebug.abi32,.note.gnu.build-id} "$ko_path_dst/$bn" fi sizeinfo mod "$ko_path_dst/$bn" found_kos="$found_kos $bn" done for ko in $(set | sed -rn 's/^FREETZ_MODULE_(.*)=y$/\1/p') $FREETZ_MODULES_OWN; do echo "$found_kos " | tr '\-+' '_x' | grep -q " $ko.ko " && continue warn "File of kernel module not found: $ko.ko" kos_missing=y done [ "$FIRMWARE_NOCOMPILE" != "1" -a -n "$kos_missing" ] && error 1 "Enable missing with 'make kernel-menuconfig' as (M)odule (and push a pull request). Use '/' to search in menuconfig." echo1 "generating modules.dep" DEPMOD_TEMP="$(mktemp)" if [ "$FREETZ_AVM_VERSION_07_2X_MIN" == "y" ]; then touch "$MODULES_DIR/modules.builtin" LANG=C depmod -e -b "$FILESYSTEM_MOD_DIR" \ -F ${KERNEL_REP_DIR}/System-${KERNEL_ID}.map \ $FREETZ_KERNEL_VERSION \ 2>&1 | tee "$DEPMOD_TEMP" else NM=$NM ${TOOLS_DIR}/depmod.pl -e -b "$MODULES_DIR" \ -F ${KERNEL_REP_DIR}/System-${KERNEL_ID}.map \ 2>&1 | tee "$DEPMOD_TEMP" fi if grep -qE "(unresolved|unknown) symbol" "$DEPMOD_TEMP"; then warn "Unresolved symbols detected, not all AVM-features may work.\nNo current sources by AVM? Error in kernel's .config? Ask fritzbox_info@avm.de for sources!" fi rm -f "$DEPMOD_TEMP" # add plugin kernel modules for 7270v1 if plugins are not enabled if [ "$FREETZ_TYPE_7270_V1" == "y" -a "$FREETZ_AVMPLUGINS_INTEGRATE" != "y" ]; then echo "kernel/drivers/net/rfcntl/rfcntl.ko: kernel/drivers/char/audio/avm_audio.ko" >> $MODULES_DIR/modules.dep echo "kernel/drivers/char/audio/avm_audio.ko:" >> $MODULES_DIR/modules.dep fi fi kolinecnt="$(cat $MODULES_DIR/modules.dep | wc -l)" kofilecnt="$(find $MODULES_DIR -type f -name '*.ko' | wc -l)" echo1 "kernel modules installed: $kolinecnt entries in modules.dep and $kofilecnt .ko-files found." if [ "$FREETZ_KERNEL_VERSION_2_6_28" == "y" ]; then if [ "$FREETZ_REPLACE_KERNEL" != "y" ];then koreplacek=", try 'replace kernel'" komaxcount=50 else komaxcount=99 fi if [ $kolinecnt -gt $komaxcount -o $kofilecnt -gt $komaxcount ]; then warn0 "This kernel can only load $komaxcount modules at the same time${koreplacek}." fi fi echo1 "removing empty kernel module directories" for dir in $(find ${MODULES_DIR} -type d -empty -delete -printf "%P\n"); do echo2 $dir done invoke_fwmod_custom all # Processing some options, must be done after base package is in place if [ "$FREETZ_INSTALL_BASE" == "y" ]; then echo0 "processing mod base options" # color scheme if [ "$FREETZ_STYLE" == "grey" ]; then echo1 "setting grey style as default" ln -s colorscheme-grey.css ${FILESYSTEM_MOD_DIR}/usr/share/style/colorscheme.css else echo1 "setting colored style as default" ln -s colorscheme-colored.css ${FILESYSTEM_MOD_DIR}/usr/share/style/colorscheme.css fi # favicon if [ "$FREETZ_FAVICON_STRING" != "none" ]; then echo1 "adding favicon(s) (${FREETZ_FAVICON_STRING})" cp "${FAVICON_DIR}/${FREETZ_FAVICON_STRING}/freetz.ico" "${FILESYSTEM_MOD_DIR}/usr/share/favicon.ico" ln -s "../share/favicon.ico" "${FILESYSTEM_MOD_DIR}/usr/mww/favicon.ico" if [ -e "${FAVICON_DIR}/${FREETZ_FAVICON_STRING}/box.ico" ]; then cp "${FAVICON_DIR}/${FREETZ_FAVICON_STRING}/box.ico" "${HTML_LANG_MOD_DIR}/html/favicon.ico" ln -fs "./html/favicon.ico" "${HTML_LANG_MOD_DIR}/favicon.ico" fi fi # security level echo1 "patching security level ($FREETZ_SECURITY_LEVEL)" sed -i -e "s/sec_level=1/sec_level=$FREETZ_SECURITY_LEVEL/g" ${FILESYSTEM_MOD_DIR}/usr/lib/libmodcgi.sh # external [ ! "$EXTERNAL_ENABLED" != "y" ] && echo1 "integrated external" # FREETZMOUNT [ ! "$FREETZ_PATCH_FREETZMOUNT" != "y" ] && echo1 "integrated FREETZMOUNT" # Box-Info [ "$FREETZ_REMOVE_BOX_INFO" != "y" ] && echo1 "integrated Box-Info" # FREETZ-Info [ "$FREETZ_REMOVE_FREETZ_INFO" != "y" ] && echo1 "integrated FREETZ-Info" # .config if [ "$FREETZ_DOT_CONFIG_DONOTADD" == "y" ]; then echo1 "integrating .config is disabled" else if [ "$FREETZ_DOT_CONFIG_STRIPPED" == "y" ]; then { grep '^[^#].*$' "$DOT_CONFIG"; grep '^#.*$' "$DOT_CONFIG.compressed"; echo "FREETZ_LIBRARY_DIR=\"${FREETZ_LIBRARY_DIR}\""; } \ | grep -v "FREETZ_FWMOD_SIGN_PASSWORD" | grep -v "^FREETZ_BUSYBOX_[^_]" > "${FILESYSTEM_MOD_DIR}/etc/.config" echo1 "integrated .config (stripped)" else { grep -v "FREETZ_FWMOD_SIGN_PASSWORD" "$DOT_CONFIG"; echo "FREETZ_LIBRARY_DIR=\"${FREETZ_LIBRARY_DIR}\""; } > "${FILESYSTEM_MOD_DIR}/etc/.config" echo1 "integrated .config (complete)" fi fi # logo tagging if [ "$FREETZ_TAGGING_ENABLED" == "y" ]; then tagging() { [ $# -lt 3 ] && return local tagging_geo="$1" local tagging_pos="$2" local tagging_arg="$3" for d in ${HTML_MOD_DIR}*; do [ ! -d "$d" ] && continue local tagging_ren="" for tagging_file in $(find "$d" -name "$tagging_arg"); do echo2 "${tagging_file}" if [ "${tagging_file##*/}" == "logo_fritzDiamond.svg" ]; then sed 's/>/&/' -i $tagging_file echo "$(tail -n+2 ${TAGGING_DIR}/${FREETZ_TAGGING_STRING}.svg)" >> $tagging_file continue fi [ "${tagging_file}" != "${tagging_file%svg}" ] && tagging_temp="${tagging_file%svg}png" || tagging_temp="" if [ -n "$tagging_temp" ]; then if ! inkscape "$tagging_file" --export-type=png --export-filename="$tagging_temp" -w 98 -h 77 -y 0 &>/dev/null; then if ! inkscape --without-gui "$tagging_file" --export-png="$tagging_temp" -w 98 -h 77 -y 0 &>/dev/null; then if ! convert -compress NONE -background NONE -resize 98x77 "$tagging_file" "$tagging_temp"; then error 1 "tagging failed on converting, is inkscape installed?" fi fi fi fi composite -dissolve 100% -gravity $tagging_pos -geometry $tagging_geo -quality 100 \ "${TAGGING_DIR}/${FREETZ_TAGGING_STRING}.png" ${tagging_temp:-$tagging_file} ${tagging_temp:-$tagging_file} [ $? -ne 0 ] && error 1 "tagging failed on compositing, is imagemagick and libpng installed?" [ -n "$tagging_temp" ] && tagging_ren="$tagging_ren ${tagging_file##*/}" && rm -f "${tagging_file}" done [ -z "$tagging_temp" ] && continue for i in $(echo "$tagging_ren" | sed 's, ,\n,g' | sort -u); do for j in $(grep -l "$i" "$d" -r); do sed "s,${i},${i%svg}png,g" -i "$j" done done done } echo1 "tagging avm webif (tag by ${FREETZ_TAGGING_STRING})" tagging "" "" logo_fritzDiamond.svg # svg since Fritz!OS 7.1x (eg 7490 07.11) tagging "+0+6" "center" fritzLogo.svg # svg since Fritz!OS 6.5x (eg 7320 06.50) tagging "+0+6" "center" kopfbalken_links.png # lua since Fritz!OS 6.2x (small logo @left, eg 7390 06.23) tagging "+0+0" "center" kopfbalken_links.gif # lua before Fritz!OS 6.2x (small logo @left, eg 7270 04.88) tagging "-20+0" "west" kopfbalken.gif # newer html (big header @top, eg 7320 05.29) tagging "+0+0" "west" fw_header980.gif # older (big header @top, eg 7141 04.76) tagging "+0-5" "west" fw_header.gif # even older (big header @top, eg 7050 04.03) fi fi if [ "$FREETZ_STRIP_LIBRARIES" == "y" ]; then echo0 "shrinking shared libs" source ${TOOLS_DIR}/freetz_mklibs mklibs || error 1 "mklibs returned an error. Please see build/modified/mklibs.log" fi if [ "$FREETZ_STRIP_MODULES_ALL" == "y" ]; then echo0 "stripping all kernel modules" for i in $(find ${MODULES_DIR} -name '*.ko'); do echo2 $i ${ABS_BASE_DIR}/toolchain/kernel/bin/${FREETZ_KERNEL_CROSS}strip -p --strip-unneeded \ --remove-section={.comment,.pdr,.mdebug.abi32,.note.gnu.build-id} $i done fi if [ "$FREETZ_STRIP_SCRIPTS" == "y" ]; then echo0 "stripping shell scripts" # This is (necessarily) slow because it checks *all* files for f in $(find ${FILESYSTEM_MOD_DIR} -type f); do # Syntax check. Use ash (not bash) because on target we also have ash. # This is the first step because it is faster than 'file'. $BUSYBOX ash -n "$f" 2>/dev/null && # Sometimes the ash syntax check succeeds on binaries. # So we need to check we really have a text file here. file -b --mime-type "$f" | grep -sq '^text/' && # Only strip scripts (possibly also stuff like awk or perl) with # shebang. This excludes dot-included files without shebang, but # anything else would be too unsafe. We do not want plain text # files stripped. grep -sq '#[^!]' "$f" || # continue the loop with the next file if one of the conditions above is false continue # Strip ... STRIP_SCRIPTS_SED_SCRIPT='/^[ \t]*$/d;' # blank lines # TODO: doesn't work because of multiline IFS definitions, i.e. IFS='\t\n' #STRIP_SCRIPTS_SED_SCRIPT+='s/[ \t]+$//;' # trailing white spaces STRIP_SCRIPTS_SED_SCRIPT+='/^[ \t]*#[^!].*/d;' # shell comments (not shebangs) if [ "${f: -3:3}" != ".py" ]; then STRIP_SCRIPTS_SED_SCRIPT+='s/^[ \t]*//g;' # and indentation if it's not a python script fi sed -i -r "${STRIP_SCRIPTS_SED_SCRIPT}" "$f" && echo2 "${f##${FILESYSTEM_MOD_DIR}}" done fi if [ "$FREETZ_STRIP_BINARIES" == "y" ]; then echo0 "stripping leftover unstripped binaries" for i in $(find \ "${FILESYSTEM_MOD_DIR}" $([ "${FREETZ_AVM_HAS_INNER_OUTER_FILESYSTEM}" == "y" -a "$FREETZ_REPLACE_OUTER_UCLIBC_AND_BUSYBOX" == "y" ] && echo "${FILESYSTEM_OUTER_MOD_DIR}") \ ! \( -name '*.ko' -o -path '*/usr/www/*' -o -path '*/etc/default*' -o -path '*/lib/modules*' \) \ \( -perm /100 -o -name "*.so*" \) \ -type f \ -exec file {} '+' | sed -n 's|^\(.*\):.* not stripped.*|\1|p' \ ); do echo2 $i chmod u+r $i $STRIP -p --remove-section={.comment,.note,.pdr} $i done fi # External should run after modifying, stripping etc. if [ "$EXTERNAL_ENABLED" == "y" ]; then echo0 "processing external" [ ! -x "$EXTERNAL" ] && error 1 "cannot find the tool $EXTERNAL_TOOL" source "${EXTERNAL}" fi touch "${DIR}/.modified" echo0 "done.\n" fi ################################################# ## Pack, sign, zip, copy the modified firmware ## ################################################# DO_AVOID_MOD_IN_STEP3=0 [ "$DO_PACK" -gt 0 ] && action_names+="/PACK" [ "$DO_SIGN" -gt 0 ] && action_names+="/SIGN" [ "$DO_ZIP" -gt 0 ] && action_names+="/ZIP" [ "$COPY_FS_DIR" ] && action_names+="/COPY" action_names=${action_names##/} # ------------------------------------------------------ # -- Common initial actions for pack, sign, zip, copy -- # ------------------------------------------------------ STEP="3" if [ "$action_names" ]; then echo0 -b "STEP 3: ${action_names}" if [ ! "$DO_MOD" -gt 0 ]; then echo "WARNING: Modifications (STEP 2) and this step should never" 1>&2 echo " ever be run with different configurations!" 1>&2 echo " This can result in invalid images!!!" 1>&2 fi [ "$FW_IMAGES_DIR" ] && mkdir -p "$FW_IMAGES_DIR" # Check if firmware is unpacked if [ ! -r "$UNPACKED_FILE" ]; then error 1 "firmware image has to be unpacked before packing" fi # Check if firmware is modified by the script if [ ! -r "${DIR}/.modified" ]; then warn "firmware does not seem to be modified by the script" DO_AVOID_MOD_IN_STEP3=1 # Check if this is a completely automated run in the "no freetz"-mode if [ "$NO_FREETZ_AUTOMATED_RUN" -gt 0 ]; then # Removing (possibly already existing) MOD_DIR is necessary # as Freetz doesn't have any checks if some of the patches # are already applied and might (try to) apply them over # and over again. rm -rf "$MOD_DIR" #else # In the manual "step by step"-mode it's up to the user to invoke # the script in a proper configuration so that the patches do not # get applied multiple times. fi if [ ! -d "$MOD_DIR" ]; then # Copy the unpacked directory cp -r "$ORG_DIR" "$MOD_DIR" fi invoke_fwmod_custom all_no_freetz fi # Remove left over version-constrol-system files echo1 "checking for left over version-control-system files" find "$MOD_DIR" \( -type d -name '.svn' \) -o \( -type d -name '.git' \) -o -name '.gitignore' | xargs rm -rf # Delete all files that we are going to re-create now rm -f "$VARTAR_MOD" rm -f "$KERNEL_MOD" rm -f "$FILESYSTEM_MOD" rm -f "${DIR}/*.image" rm -f "${FIRMWARE_MOD_DIR}/var/signature" # Assemble output file name get_modstring() { local modstring= local prefix= local brandings= local languages= #PREFIX if [ "$FREETZ_IMAGE_NAME_PREFIX" == "y" ]; then prefix="$(echo $FREETZ_USER_DEFINED_COMMENT | sed -e "s/ /_/g" | tr -cd 'a-zA-Z0-9_+-.<->')" [ -n "${prefix}" ] && modstring="${prefix%%_}_" fi #DEVICE if [ "$FREETZ_IMAGE_NAME_DEVICE" == "y" ] \ || [ -z "$FREETZ_IMAGE_NAME_CUSTOM" ]; then [ -n "$FREETZ_TYPE_PREFIX_ALIEN_HARDWARE" ] && modstring+="${FREETZ_TYPE_PREFIX_ALIEN_HARDWARE/_/}" || modstring+="${FREETZ_TYPE_PREFIX/_/}" fi #ALIEN if [ "$FREETZ_IMAGE_NAME_ALIEN" == "y" ] \ || [ -z "$FREETZ_IMAGE_NAME_CUSTOM" -a -n "$FREETZ_TYPE_PREFIX_ALIEN_HARDWARE" ]; then modstring+="-Alien${FREETZ_TYPE_PREFIX/_/}" fi #ANNEX if [ "$FREETZ_IMAGE_NAME_ANNEX" == "y" ] \ || [ -z "$FREETZ_IMAGE_NAME_CUSTOM" -a "$FREETZ_AVM_HAS_ANNEX_A_AND_B" == "y" ]; then modstring+="-Annex" [ "$FREETZ_TYPE_ANNEX_A" == "y" ] && modstring+="A" [ "$FREETZ_TYPE_ANNEX_B" == "y" ] && modstring+="B" fi #FRITZOS if [ "$FREETZ_IMAGE_NAME_FRITZOS" == "y" ] \ || [ -z "$FREETZ_IMAGE_NAME_CUSTOM" ]; then modstring+="_${AVM_FW_VERSION}" fi #REGION if [ "$FREETZ_IMAGE_NAME_REGION" == "y" ] \ || [ -z "$FREETZ_IMAGE_NAME_CUSTOM" ]; then modstring+=".$(echo ${FREETZ_TYPE_LANGUAGE} | sed 's/^de$/ger/;s/^en$/int/;s/^xx$/all/;s/^a-ch$/ach/;s/^it$/ita/')" fi #CHECKPOINT if [ "$FREETZ_IMAGE_NAME_CHECKPOINT" == "y" ] \ || [ -z "$FREETZ_IMAGE_NAME_CUSTOM" -a -n "$FREETZ_TYPE_PREFIX_LABOR_FIRMWARE" ]; then modstring+="-rev${AVM_FW_REVISION}" fi #RELEASECYCLE if [ "$FREETZ_IMAGE_NAME_RELEASECYCLE" == "y" ]; then RELEASECYCLE="$(sed -rn 's/^Releasecycle=//p' "${FIRMWARE_DIR}/var/content" 2>/dev/null)" [ -n "$RELEASECYCLE" ] && modstring+="_${RELEASECYCLE/ /-}" fi #BUILDTYPE if [ "$FREETZ_IMAGE_NAME_BUILDTYPE" == "y" ] \ || [ -z "$FREETZ_IMAGE_NAME_CUSTOM" -a -n "$FREETZ_TYPE_PREFIX_LABOR_FIRMWARE" ]; then modstring+="${FREETZ_TYPE_PREFIX_LABOR_FIRMWARE:-_release}" fi #BRANDINGS if [ "$FREETZ_IMAGE_NAME_BRANDINGS" == "y" ]; then for x in $(sed -rn 's/^FREETZ_AVM_HAS_BRANDING_(.*)=y$/\1/p' "$DOT_CONFIG" | sort); do [ "$(eval "echo \"\$FREETZ_REMOVE_BRANDING_$x\"")" != "y" ] && brandings+="-$x" done modstring+="_${brandings#-}" fi #LANGUAGES if [ "$FREETZ_IMAGE_NAME_LANGUAGES" == "y" ]; then for x in $( (sed -n 's/^language //p' $FILESYSTEM_DIR/etc/*.language && \ ls $FILESYSTEM_DIR/etc/htmltext_??.db 2>/dev/null | sed -rn 's/.*_(..)\.db/\1/p') | sort -u); do [ "$(eval "echo \"\$FREETZ_REMOVE_LANGUAGE_$x\"")" != "y" ] && languages+="-$x" done modstring+="_${languages#-}" fi #FREETZ if [ "$FREETZ_IMAGE_NAME_FREETZ" == "y" ] \ || [ -z "$FREETZ_IMAGE_NAME_CUSTOM" ]; then [ -n "$FREETZ_VERSION" ] && modstring+="_${FREETZ_VERSION}" # missing in DO_MOD=0 mode fi #TIMESTAMP if [ "$FREETZ_IMAGE_NAME_TIMESTAMP" == "y" ] \ || [ -z "$FREETZ_IMAGE_NAME_CUSTOM" ]; then modstring+="_${modmakedate}" fi #EXTRA if [ -n "${FREETZ_IMAGE_NAME_EXTRA}" ]; then modstring+="-${FREETZ_IMAGE_NAME_EXTRA}" fi #done echo -n "$modstring" } modmakedate="$(date +%Y%m%d-%H%M%S)" modstring="$(get_modstring)" # collect externalized files externalised_files=$(find "$EXTERNAL_MOD_DIR/" -type f 2>/dev/null | sed -e "/external[.]pkg/d;/[.]external/d;s,$EXTERNAL_MOD_DIR/,,") if [ ! "$DO_AVOID_MOD_IN_STEP3" -gt 0 ]; then # Create freetz-info echo1 "integrate freetz info file into image" freetz_info_file="$MOD_DIR/filesystem/etc/freetz_info.cfg" echo "export FREETZ_INFO_BOXTYPE='${FREETZ_TYPE_PREFIX_ALIEN_HARDWARE}${FREETZ_TYPE_PREFIX%_0?_??}${FREETZ_TYPE_PREFIX_LABOR_FIRMWARE}'" > "$freetz_info_file" echo "export FREETZ_INFO_FIRMWAREVERSION='${AVM_FW_VERSION}'" >> "$freetz_info_file" echo "export FREETZ_INFO_VERSION='${FREETZ_VERSION}'" >> "$freetz_info_file" echo "export FREETZ_INFO_LANG='${FREETZ_TYPE_LANGUAGE}'" >> "$freetz_info_file" echo "export FREETZ_INFO_MAKEDATE='${modmakedate}'" >> "$freetz_info_file" echo "export FREETZ_INFO_IMAGE_NAME='${modstring}.image'" >> "$freetz_info_file" echo "export FREETZ_INFO_COMMENT='${FREETZ_USER_DEFINED_COMMENT}'" >> "$freetz_info_file" echo "export FREETZ_INFO_EXTERNAL_FILES='${externalised_files}'" >> "$freetz_info_file" fi # Pack var.tar (use old tar for compatibility) echo0 "packing var.tar" "$TAR" -C "$VARTAR_MOD_DIR" -cf "$VARTAR_MOD" . if [ $? -ne 0 ] || ! is_valid_tarball "$VARTAR_MOD"; then mv "${VARTAR_MOD}" "${VARTAR_MOD}.corrupted" 2>/dev/null error 1 "packing of var.tar failed" fi if [ "$FREETZ_AVM_HAS_UDEV" != "y" ]; then [ -s "$MAKEDEVS_FILE" ] || error 1 "file $MAKEDEVS_FILE not found or empty" $MAKEDEVS -d $MAKEDEVS_FILE $FILESYSTEM_MOD_DIR > $MOD_DIR/filesystem.log 2>&1 [ $? -ne 0 ] && cat $MOD_DIR/filesystem.log && error 1 "makedevs failed" fi fi # ------------------------------------------- # -- Check and maybe create signature keys -- # ------------------------------------------- if [ "$DO_SIGN" -gt 0 ]; then echo1 "checking signature key files" if [ ${#FREETZ_FWMOD_SIGN_PASSWORD} -lt 6 ]; then while true; do read -sp "Enter password for private signature key file (hidden input): " FREETZ_FWMOD_SIGN_PASSWORD echo if [ -s "${SIGNATURE_SUBDIR}/prv" -a ${#FREETZ_FWMOD_SIGN_PASSWORD} -ge 6 ]; then openssl rsa -in "${SIGNATURE_SUBDIR}/prv" -passin "pass:$FREETZ_FWMOD_SIGN_PASSWORD" -noout &>/dev/null && break echo "Password is wrong, try again!" else [ ${#FREETZ_FWMOD_SIGN_PASSWORD} -ge 6 ] && break echo "To short password, try again!" fi done fi #dir [ ! -e "${SIGNATURE_SUBDIR}" -a ! -L "${SIGNATURE_SUBDIR}" ] && \ ln -s ~/.freetz-signature "${SIGNATURE_SUBDIR}" [ ! -d "${SIGNATURE_SUBDIR}" ] && \ mkdir -p "$(readlink "${SIGNATURE_SUBDIR}")" [ ! -d "${SIGNATURE_SUBDIR}" ] && \ error 1 "can not create ./${SIGNATURE_SUBDIR} directory" #prv if [ ! -s "${SIGNATURE_SUBDIR}/prv" ]; then echo2 "creating private signature key file" rm -f "${SIGNATURE_SUBDIR}/prv" "${SIGNATURE_SUBDIR}/pub" openssl genrsa -aes128 -passout "pass:$FREETZ_FWMOD_SIGN_PASSWORD" -out "${SIGNATURE_SUBDIR}/prv" 1024 >/dev/null 2>&1 || \ error 1 "could not create private signature key file" else openssl rsa -in "${SIGNATURE_SUBDIR}/prv" -passin "pass:$FREETZ_FWMOD_SIGN_PASSWORD" -noout >/dev/null 2>&1 || \ error 1 "wrong password for private signature key file" fi #pub if [ ! -s "${SIGNATURE_SUBDIR}/pub" ]; then echo2 "creating public signature key file" EXP="$(openssl rsa -in "${SIGNATURE_SUBDIR}/prv" -passin "pass:$FREETZ_FWMOD_SIGN_PASSWORD" -noout -text | sed -rn 's/^publicExponent:.*\(0x(.*)\).*/\1/p')" MOD="$(openssl rsa -in "${SIGNATURE_SUBDIR}/prv" -passin "pass:$FREETZ_FWMOD_SIGN_PASSWORD" -noout -modulus | sed -rn 's/^Modulus=(.*)/\1/p')" [ $(( ${#EXP} % 2 )) != 0 ] && EXP="0$EXP" [ $(( ${#MOD} % 2 )) != 0 ] && MOD="0$MOD" [ "${MOD:0:2}" != "00" ] && MOD="00$MOD" echo -e "$MOD\n$EXP" > "${SIGNATURE_SUBDIR}/pub" [ "$(stat -c%s "${SIGNATURE_SUBDIR}/pub" 2>/dev/null)" != "266" ] && \ error 1 "could not create public signature key file" fi #cpy echo2 "adding public signature key file" cp -p "${SIGNATURE_SUBDIR}/pub" "${FILESYSTEM_MOD_DIR}/etc/avm_firmware_public_key8" fi # ------------------------------------------------------------------ # -- Zip file system to tar.gz archive (USB root, maybe NFS root) -- # ------------------------------------------------------------------ if [ "$DO_ZIP" -gt 0 ]; then if [ "$FW_IMAGES_DIR" ]; then zip_name="${FW_IMAGES_DIR}/${modstring}_rootfs.tar.gz" else zip_name="${DIR}/${modstring}_rootfs.tar.gz" fi echo0 "zipping root file system to $zip_name" "$TAR" -C "$FILESYSTEM_MOD_DIR" -czf "$zip_name" . if [ $? -ne 0 ] || ! is_valid_tarball "$zip_name"; then mv "${zip_name}" "${zip_name}.corrupted" 2>/dev/null error 1 "zipping of root file system failed" fi echo "$zip_name" > "${DIR}/.rootfs_archive" fi # ------------------------- # -- Pack firmware image -- # ------------------------- if [ "$DO_PACK" -gt 0 ]; then [ ! -x "$MKSQUASHFS" ] && error 1 "cannot find $MKSQUASHFS" if [ "$FREETZ_AVM_PROP_INNER_FILESYSTEM_TYPE_CPIO" == "y" ]; then echo0 "creating ${INNER_FS_PREFIX}filesystem image (CPIO-gz)" find $FILESYSTEM_MOD_DIR/ -mindepth 1 -printf '%P\n' | cpio -o --quiet -H newc -D $FILESYSTEM_MOD_DIR/ | gzip -9 > $ABS_BASE_DIR/${MAIN_FILESYSTEM_MOD} else echo0 "creating ${INNER_FS_PREFIX}filesystem image (SquashFS${FREETZ_SQUASHFS_VERSION}-${FREETZ_AVM_SQUASHFS_COMPRESSION})" echo1 "SquashFS block size: $(($FREETZ_SQUASHFS_BLOCKSIZE/1024)) kB ($FREETZ_SQUASHFS_BLOCKSIZE bytes)" rm -f $ABS_BASE_DIR/${MAIN_FILESYSTEM_MOD} "$MKSQUASHFS" $FILESYSTEM_MOD_DIR/* $ABS_BASE_DIR/${MAIN_FILESYSTEM_MOD} $MKSQUASHFS_OPTIONS >> $MOD_DIR/filesystem.log 2>&1 fi if [ "${FREETZ_AVM_HAS_SEPARATE_FILESYSTEM_IMAGE}" == "y" ]; then echo0 "copying kernel image" cp -a "$RAW_KERNEL_MOD" "$KERNEL_MOD" else [ ! -s "$RAW_FILESYSTEM_MOD" ] && error 1 "creation of filesystem failed" touch "$FILESYSTEM_MOD" echo0 "merging kernel image" dd if="$RAW_KERNEL_MOD" of="$KERNEL_MOD" bs=256 conv=sync 2> /dev/null cat "$RAW_FILESYSTEM_MOD" >> "$KERNEL_MOD" [ ! -s "$KERNEL_MOD" ] && error 1 "kernel merging failed" fi # Check size of kernel image (multiple of 64 kB blocks) if [ -n "$FREETZ_KERNEL_CUSTOM_MTD_SIZE" ]; then let KERNEL_LIMIT="$FREETZ_KERNEL_CUSTOM_MTD_SIZE*64*1024" elif [ -e "$FIRMWARE_MOD_DIR/var/firmware-update.uimg" ]; then KERNEL_LIMIT= # kernel_size seems to be for ARM and not ATOM, so ignore it as real size is not known - and RK not available else KERNEL_LIMIT="$(sed -nr 's/^kernel_size=(.*)/\1/p' ${FIRMWARE_DIR}/var/install)" # [ -z "$KERNEL_LIMIT" ] && error 1 "Can't find kernel_size in var/install" fi KERNEL_SIZE="$(wc -c < "$KERNEL_MOD")" [ "$KERNEL_SIZE" -eq 0 ] && error 1 "kernel image is empty" if [ -z "$KERNEL_LIMIT" ]; then echo1 "kernel image size: $(byte_to_mb $KERNEL_SIZE)" else let KERNEL_DIFF="KERNEL_SIZE-KERNEL_LIMIT" echo1 "kernel image size: $(byte_to_mb $KERNEL_SIZE), max $(byte_to_mb $KERNEL_LIMIT), free $(byte_to_mb $((-KERNEL_DIFF))) ($((-KERNEL_DIFF)) bytes)" if [ "$KERNEL_SIZE" -gt "$KERNEL_LIMIT" ]; then if [ "${FREETZ_AVM_HAS_SEPARATE_FILESYSTEM_IMAGE}" == "y" ]; then error 1 -b "kernel image is $KERNEL_DIFF bytes too big. See https://freetz-ng.github.io/freetz-ng/wiki/00_FAQ/FAQ.de.html#filesystem-image-too-big for details." else if [ "$FORCE_PACK" -eq 0 -a "$DO_ZIP" -eq 0 ]; then error 1 -b "combined kernel+filesystem image is $KERNEL_DIFF bytes too big. See https://freetz-ng.github.io/freetz-ng/wiki/00_FAQ/FAQ.de.html#filesystem-image-too-big for details." fi if [ "$FORCE_PACK" -gt 0 -a "$DO_ZIP" -eq 0 ]; then echo0 -b "Use for SDK mode only. See https://web.archive.org/20200701000000/wehavemorefun.de/fritzbox/SDK-Firmware" fi if [ "$FORCE_PACK" -eq 0 -a "$DO_ZIP" -gt 0 ]; then echo0 -b "Use for USBroot or NFSroot mode only." fi fi fi fi # --------------------------- # -- Pack filesystem image -- # --------------------------- if [ "${FREETZ_AVM_HAS_SEPARATE_FILESYSTEM_IMAGE}" == "y" ]; then if [ "${FREETZ_AVM_HAS_INNER_OUTER_FILESYSTEM}" == "y" ]; then if [ "${FREETZ_AVM_OUTER_FILESYSTEM_TYPE}" == "Ext2FS" ]; then echo0 "creating outer-filesystem image (Ext2FS)" PATH="$TOOLS_DIR:$PATH" $TOOLS_DIR/mke2img -G 2 -R 0 -d "${FILESYSTEM_OUTER_MOD_DIR}" -o "$ABS_BASE_DIR/$RAW_FILESYSTEM_MOD.ext2" >> $MOD_DIR/filesystem.log 2>&1 [ $? -ne 0 -o ! -s "$RAW_FILESYSTEM_MOD.ext2" ] && error 1 "creation of ext2 image failed" { # create pseudo SquashFS-header: "sqsh" followed by 252 zeros echo -n "sqsh" > "$RAW_FILESYSTEM_MOD" && \ dd if=/dev/zero of="$RAW_FILESYSTEM_MOD" bs=1 count=252 oflag=append conv=notrunc } >> $MOD_DIR/filesystem.log 2>&1 && \ cat "$RAW_FILESYSTEM_MOD.ext2" >> "$RAW_FILESYSTEM_MOD" && \ rm -f "$RAW_FILESYSTEM_MOD.ext2" elif [ "${FREETZ_AVM_OUTER_FILESYSTEM_TYPE}" == "SquashFS" ]; then echo0 "creating outer-filesystem image (SquashFS${FREETZ_SQUASHFS_VERSION}-${FREETZ_AVM_SQUASHFS_COMPRESSION})" "$MKSQUASHFS" ${FILESYSTEM_OUTER_MOD_DIR}/* $ABS_BASE_DIR/$RAW_FILESYSTEM_MOD $MKSQUASHFS_OPTIONS >> $MOD_DIR/filesystem.log 2>&1 else error 1 "unknown/unsupported outer-filesystem type \"${FREETZ_AVM_OUTER_FILESYSTEM_TYPE}\"" fi fi [ ! -s "$RAW_FILESYSTEM_MOD" ] && error 1 "creation of filesystem failed" let FILESYSTEM_SIZE="$(wc -c < "$RAW_FILESYSTEM_MOD")" [ "$FILESYSTEM_SIZE" -eq 0 ] && error 1 "filesystem image is empty" echo0 "copying filesystem image" rm -f "$FILESYSTEM_MOD" "$FILESYSTEM_MOD.ext2" cp -a "$RAW_FILESYSTEM_MOD" "$FILESYSTEM_MOD" # Check size of filesystem image (multiple of 64 kB blocks) if [ -n "$FREETZ_FILESYSTEM_CUSTOM_MTD_SIZE" ]; then let FILESYSTEM_LIMIT="$FREETZ_FILESYSTEM_CUSTOM_MTD_SIZE*64*1024" else FILESYSTEM_LIMIT="$(sed -nr 's/^filesystem_size=(.*)/\1/p' ${FIRMWARE_DIR}/var/install)" # [ -z "$FILESYSTEM_LIMIT" ] && error 1 "Can't find filesystem_size in var/install" fi let FILESYSTEM_SIZE="$(wc -c < "$FILESYSTEM_MOD")" [ "$FILESYSTEM_SIZE" -eq 0 ] && error 1 "filesystem image is empty" if [ -z "$FILESYSTEM_LIMIT" ]; then echo1 "filesystem image size: $(byte_to_mb $FILESYSTEM_SIZE)" else let FILESYSTEM_DIFF="FILESYSTEM_SIZE-FILESYSTEM_LIMIT" echo1 "filesystem image size: $(byte_to_mb $FILESYSTEM_SIZE), max $(byte_to_mb $FILESYSTEM_LIMIT), free $(byte_to_mb $((-FILESYSTEM_DIFF))) ($((-FILESYSTEM_DIFF)) bytes)" if [ "$FILESYSTEM_SIZE" -gt "$FILESYSTEM_LIMIT" ]; then if [ "$FORCE_PACK" -eq 0 -a "$DO_ZIP" -eq 0 ]; then error 1 -b "filesystem image is $FILESYSTEM_DIFF bytes too big. See https://freetz-ng.github.io/freetz-ng/wiki/00_FAQ/FAQ.de.html#filesystem-image-too-big for details." fi if [ "$FORCE_PACK" -ne 0 -o "$DO_ZIP" -ne 0 ]; then echo0 -b "Use for USBroot or NFSroot mode only." fi fi fi fi if [ "$FREETZ_VERBOSITY_LEVEL" -ge 1 -a -n "$KERNEL_LIMIT" ]; then if [ "$FREETZ_AVM_HAS_TAM" = "y" -a "${FREETZ_AVM_HAS_SEPARATE_FILESYSTEM_IMAGE}" != "y" ]; then # Calculate aproximately free space in seconds for the answering machine # 5*64kB sectors needed, see #1680 FREE_BYTE_JFFS2=$((($KERNEL_LIMIT - $KERNEL_SIZE - 327680))) FREE_MINUTES=$((($FREE_BYTE_JFFS2 / 2017 / 60))) if [ "$FREE_BYTE_JFFS2" -gt 0 ]; then echo "${L1}Aproximately maximal time for the answering machine: ${FREE_MINUTES} min, $((($FREE_BYTE_JFFS2 / 2017 - $FREE_MINUTES * 60))) sec ($((($FREE_BYTE_JFFS2 / 2017))) sec)" else if [ "$FREETZ_REMOVE_JFFS2" != "y" ]; then echo "${L1}WARNING: Not enough free flash space for answering machine!" else echo "${L1}Telephone answering machine will need a usb storage device!" fi fi fi fi # Write checksum if [ ! -e "$FIRMWARE_MOD_DIR/var/firmware-update.uimg" -a ! -e "$FIRMWARE_MOD_DIR/var/tmp/fit-image" ]; then for f in "$KERNEL_MOD" "$FILESYSTEM_MOD"; do [ -s "$f" ] || continue fbn=$(basename $f) echo0 "adding checksum to $fbn" "$TICHKSUM" -a "$f" > "${MOD_DIR}/$fbn-chksum.log" || error 1 "adding checksum to $fbn failed" done fi # Consistency check if [ -s "${FIRMWARE_DIR}/${KERNEL_IMAGE}" -a ! -s "${FIRMWARE_MOD_DIR}/${KERNEL_IMAGE}" ] || \ [ ! -s "${FIRMWARE_DIR}/${KERNEL_IMAGE}" -a -s "${FIRMWARE_MOD_DIR}/${KERNEL_IMAGE}" ]; then error 1 "inconsistency comparing size of old and new kernel.image" fi if [ ! "$DO_AVOID_MOD_IN_STEP3" -gt 0 ]; then # Last, but not least, include .config and .packages into firmware # image for further reference, e.g. user support [ -r "$DOT_CONFIG" ] && { cat "$DOT_CONFIG" | grep -v "FREETZ_FWMOD_SIGN_PASSWORD" > "$FIRMWARE_MOD_DIR/var/.config"; } [ -r "$PACKAGES_LIST_FILE" ] && cut "$PACKAGES_LIST_FILE" -d ' ' -f 2,3 > "$FIRMWARE_MOD_DIR/var/.packages" fi # Set img_name for pack, sign & link img_name="${FW_IMAGES_DIR:-$DIR}/${modstring}.image" # Pack firmware image if [ -e "$FIRMWARE_MOD_DIR/var/firmware-update.uimg" ]; then echo0 "packing uimg file" mv "$FIRMWARE_MOD_DIR/var/remote/var/tmp/x86/filesystem.image" $FIRMWARE_MOD_DIR/var/*_ATOM_ROOTFS.bin mv "$FIRMWARE_MOD_DIR/var/remote/var/tmp/x86/kernel.image" $FIRMWARE_MOD_DIR/var/*_ATOM_KERNEL.bin rm "$FIRMWARE_MOD_DIR/var/remote" "$FIRMWARE_MOD_DIR/var/firmware-update.uimg" -r "${TOOLS_DIR}/uimg" -p "$FIRMWARE_MOD_DIR/var/firmware-update.uimg" >/dev/null rm $FIRMWARE_MOD_DIR/var/firmware-update_*.bin # size info UIMG_SIZE="$(wc -c < "$FIRMWARE_MOD_DIR/var/firmware-update.uimg")" echo1 "uimg file size: $(byte_to_mb $((UIMG_SIZE))) ($((UIMG_SIZE)) bytes)" elif [ -e "$FIRMWARE_MOD_DIR/var/tmp/fit-image" ]; then echo0 "packing fitimg file" OLD_SIZE="$(stat -L -c %s $FITIMAGE_MOD_DIR/filesystem.image)" for x in kernel filesystem; do mv "$FIRMWARE_MOD_DIR/var/tmp/$x.image" "$FITIMAGE_MOD_DIR/$x.image"; done NEW_SIZE="$(stat -L -c %s $FITIMAGE_MOD_DIR/filesystem.image)" # padding @1MB for "filesystems" XXX_LOAD="$(sed -rn "s/.*mtdram=(ram-filesystem|rootfs_ram),([^,]*),.*/\2/p" "$FITIMAGE_MOD_DIR/args.txt")" if [ -n "$XXX_LOAD" ]; then OLD_ADDR="$(printf '%.8x' $(( $XXX_LOAD + $OLD_SIZE + (1024*1024) - $OLD_SIZE % (1024*1024) )) )" NEW_ADDR="$(printf '%.8x' $(( $XXX_LOAD + $NEW_SIZE + (1024*1024) - $NEW_SIZE % (1024*1024) )) )" OLD_ARGS="$(cat "$FITIMAGE_MOD_DIR/args.txt")" NEW_ARGS="$(cat "$FITIMAGE_MOD_DIR/args.txt" | sed "s/$OLD_SIZE/$NEW_SIZE/;s/$OLD_ADDR/$NEW_ADDR/")" sed -i "s/$OLD_ARGS/$NEW_ARGS/" "$FITIMAGE_MOD_DIR/image.its" fi # make fit image with avm-magic SOURCE_DATE_EPOCH="$(cat "$FITIMAGE_MOD_DIR/date.txt")" $TOOLS_DIR/fit/mkimage -f "$FITIMAGE_MOD_DIR/image.its" "$FITIMAGE_MOD_DIR/image.itb" >/dev/null || error 1 "packing failed" $TOOLS_DIR/yf/fit_tools/fit-add-avm-header.sh -k "$FIRMWARE_DIR/var/tmp/fit-image" "$FITIMAGE_MOD_DIR/image.itb" > "$FIRMWARE_MOD_DIR/var/tmp/fit-image" || error 1 "packing failed" # size info FITIMAGE_LIMIT="$(( $FREETZ_AVM_HAS_FIT_SIZE *1024*1024 ))" FITIMAGE_SIZE="$(wc -c < "$FIRMWARE_MOD_DIR/var/tmp/fit-image")" let FITIMAGE_DIFF="FITIMAGE_SIZE-FITIMAGE_LIMIT" echo1 "fitimg file size: $(byte_to_mb $FITIMAGE_SIZE), max $(byte_to_mb $FITIMAGE_LIMIT), free $(byte_to_mb $((-FITIMAGE_DIFF))) ($((-FITIMAGE_DIFF)) bytes)" fi echo0 "packing ${img_name}" "$TAR_GNU" -f "${img_name}" --owner=0 --group=0 --mode=0755 --format=oldgnu -C "$FIRMWARE_MOD_DIR" --create ./var if [ $? -ne 0 ] || ! is_valid_tarball "${img_name}"; then mv "${img_name}" "${img_name}.packed.corrupted" 2>/dev/null error 1 "packing of firmware image failed" fi echo1 "packed image file size: $(byte_to_mb $(wc -c < "${img_name}")) ($(wc -c < "${img_name}") bytes)" # Sign firmware image if [ "$DO_SIGN" -eq 1 ]; then echo1 -l "signing packed .image file" if [ "$FREETZ_FWMOD_SIGN_METHOD_SI" == "y" ]; then ln -fs "${SIGNATURE_SUBDIR}/prv" "sign-image.key" FREETZ_IMAGE_SIGNING_PREFIX="sign-image" ${TOOLS_DIR}/yf/signimage/yf_sign \ "${img_name}" "$FREETZ_FWMOD_SIGN_PASSWORD" > "${img_name}.signed-temp" 2> "${img_name}.signed.debug-out" RET=$? [ $RET -ne 0 ] && cat "${img_name}.signed.debug-out" rm -f "sign-image.key" "${img_name}.signed.debug-out" mv -f "${img_name}.signed-temp" "${img_name}" else openssl md5 -sign "${SIGNATURE_SUBDIR}/prv" -passin "pass:$FREETZ_FWMOD_SIGN_PASSWORD" -out "${FIRMWARE_MOD_DIR}/var/signature" "${img_name}" || \ error 1 "could not create signature file for firmware image" "$TAR_GNU" -f "${img_name}" --owner=0 --group=0 --mode=0755 --format=oldgnu -C "$FIRMWARE_MOD_DIR" --append ./var/signature RET=$? fi if [ $RET -ne 0 ] || ! is_valid_tarball "${img_name}"; then mv "${img_name}" "${img_name}.signed.corrupted" 2>/dev/null error $RET "adding signature to firmware image failed" fi echo1 "signed image file size: $(byte_to_mb $(wc -c < "${img_name}")) ($(wc -c < "${img_name}") bytes)" fi echo1 -l "source firmware: ${SOURCE_IMAGE_DETAILS} ${SOURCE_IMAGE_SIZE}" echo1 "source image file size: $(byte_to_mb $(wc -c < "${FIRMWARE}")) ($(wc -c < "${FIRMWARE}") bytes)" # create the link images/latest.image to the just created .image img_link="${img_name%/*}/latest.image" rm -f "$img_link" ln -s "${img_name#*/}" "$img_link" fi # ---------------------------------------------- # -- Common final actions for pack, zip, copy -- # ---------------------------------------------- if [ "$action_names" ]; then # Pack externalised files if [ "$EXTERNAL_CREATEPAK" == "y" -a -n "$externalised_files" ]; then #static packages modexternal="${FW_IMAGES_DIR:-$DIR}/${modstring}.external" echo "packing ${modexternal}" "$TAR" -C "$EXTERNAL_MOD_DIR" -cf "$modexternal" . if [ $? -ne 0 ] || ! is_valid_tarball "$modexternal"; then mv "${modexternal}" "${modexternal}.corrupted" 2>/dev/null error 1 "packing of external tar failed" fi echo1 "external file size: $(byte_to_mb $(wc -c < "$modexternal"))" #dynamic packages if [ "$EXTERNAL_CREATEPAK_DYNAMIC" == "y" ]; then shopt -s nullglob for pkg in ${EXTERNAL_MOD_DIR}-*; do pkg=${pkg#${EXTERNAL_MOD_DIR}-} pkgexternal="${FW_IMAGES_DIR:-$DIR}/${modstring}_${pkg}.external" echo "packing ${pkgexternal}" "$TAR" -C "$EXTERNAL_MOD_DIR-${pkg}" -cf "$pkgexternal" . if [ $? -ne 0 ] || ! is_valid_tarball "$pkgexternal"; then mv "${pkgexternal}" "${pkgexternal}.corrupted" 2>/dev/null error 1 "packing of external-$pkg tar failed" fi echo1 "package file size: $(byte_to_mb $(wc -c < "$pkgexternal"))" done shopt -u nullglob fi fi if [ "$FREETZ_REPLACE_OPENSSL" == "y" ] && [ "$FREETZ_LIB_libcrypto" == "y" -o "$FREETZ_LIB_libssl" == "y" ]; then echo "Caution: Replacing libcrypto or libssl may cause an unusable image." echo "See https://freetz-ng.github.io/freetz-ng/wiki/00_FAQ/FAQ.de.html#nach-dem-flashen-ist-das-avm-webinterface-nicht-mehr-erreichbar for details." fi [ "$COPY_FS_DIR" ] || echo -e "done.\n" fi exit 0