123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- #!/bin/bash
- # (c) 2015 Helge Jung <hej@c3pb.de>
- #
- # This script is controlled by environment variables,
- # only the first being mandatory:
- #
- # CANDIDATE = directory in which to find the to-be-checked firmware images
- # REFERENCE = directory of your build firmware, defaults to './src/images'
- # MANIFEST = if given, use files referenced in Gluon manifest file
- # if left empty (unset), 'find' is used to examine all '.bin' files
- # VERBOSE = 0 (default) or 1, putting lots of debug output
- #
- MY_DIR=$(dirname $0)
- MY_DIR=$(readlink -f "$MY_DIR")
- pushd "$MY_DIR" > /dev/null
- . functions.sh
- # check for necessary tools
- for tool in bbe binwalk find gawk unsquashfs; do
- [ -x "$(which $tool)" ] || abort "Missing necessary tool '$tool'."
- done
- # check that CANDIDATE dir is given and existing
- [ "_$CANDIDATE" == "_" ] && abort "Please specify CANDIDATE environment variable point to the directory of to-be-checked firmware images."
- [ ! -d "$CANDIDATE" ] && abort "The directory indicated by CANDIDATE was not found."
- CANDIDATE=$(readlink -f $CANDIDATE)
- # set defaults for environment variables
- [ -n "${REFERENCE}" ] || REFERENCE="./src/images"
- if [ "_$VERBOSE" == "_1" ]; then VERBOSE=1; else VERBOSE=0; fi
- # assemble file list
- declare -a FILELIST
- if [ -n "$MANIFEST" ]; then
- progress "Assembling file list from manifest file ..."
- FILELIST=()
- else
- [ ! -d "$REFERENCE" ] && abort "The REFERENCE directory was not found. Have you built the firmware?"
- REFERENCE=$(readlink -f $REFERENCE)
- progress "Assembling file list ..."
- FILELIST=($(find "$REFERENCE" -type f -name "*.bin"))
- fi
- COUNT=${#FILELIST[*]}
- [ "$COUNT" = 0 ] && abort "No firmware files found. Please check that you built software in the REFERENCE dir."
- info "Need to check $COUNT files."
- # setup temp dir for checking
- TEMPDIR=$(mktemp -d)
- debug "Temporary dir = $TEMPDIR"
- # check each file
- IDX=0
- declare -a ERRORS
- filter_timestamp() {
- file=$1
- cp "$file" "$file.orig"
- egrep -ao '(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) [0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2} UTC [0-9]{4}' "$file" | sort -u | while read ts; do
- debug "Normalizing timestamp: '$ts'"
- bbe -e "s/$ts/Abc Def 12 34:56:78 UTC 9010/" -o "${file}" "${file}.orig"
- done
- }
- for ref in ${FILELIST[*]}; do
- IDX=$(($IDX + 1))
- NAME=`basename "$ref"`
- [ $VERBOSE -eq 1 ] && progress "[${IDX}/${COUNT}] $NAME"
- if [ ! -r "$ref" ]; then
- ERRORS=( "${ERRORS[@]}" "$NAME: missing reference file ($ref)" )
- continue
- fi
- cand=$(readlink -f "${CANDIDATE}/${NAME}")
- if [ ! -r "$cand" ]; then
- ERRORS=( "${ERRORS[@]}" "$NAME: missing candidate file in $CANDIDATE" )
- continue
- fi
- pushd "$TEMPDIR" > /dev/null
- rm -Rf candidate ; mkdir candidate
- rm -Rf reference ; mkdir reference
- # TODO: check output of binwalk that there are only the two expected parts
- cd candidate
- binwalk -qe "$cand" 2>/dev/null
- cd ../reference
- binwalk -qe "$ref" 2>/dev/null
- cd ..
- # check ROM part
- debug "Filtering timestamps in ROM part (uboot+kernel) ..."
- filter_timestamp candidate/200
- filter_timestamp reference/200
- hash_rom_cand=$(sha512sum candidate/200)
- hash_rom_ref=$(sha512sum reference/200)
- if [ "$hash_rom_cand" != "$hash_rom_ref" ]; then
- ERRORS=( "${ERRORS[@]}" "$NAME: ROM part mismatch" )
- debug "Calling vbindiff for your visual pleasure."
- vbindiff reference/200 candidate/200
- fi
- # extract root filesystem
- for dir in candidate reference; do
- cd $dir
- unsquashfs -n -f *.squashfs > /dev/null
- cd ..
- done
- fsdiff=$(diff -ur reference/squashfs-root candidate/squashfs-root 2>&1)
- # TODO: intelligent diff statt 'diff -r', Verhalten abhängig vom Dateinamen
- # squashfs-root/usr/lib/opkg/info/*.list: erst sortieren, dann diffen
- # squashfs-root/usr/lib/opkg/info/*.control: Unterschied in "Installed Size" ignorieren (kommt vermutlich durch unterschiedliche Reihenfolge und Block-Alignments?)
- # squashfs-root/usr/lib/opkg/status: Delta in "Installed-Time: " Zeilen ignorieren
- # squashfs-root/usr/lib/lua/luci/version.lua: neoraider/openwrt hauen, die Änderung im luciversion-String kommt durch manuelles git patching
- # else: binary file compare, sha512sum
- if [ "$?" -ne 0 ]; then
- ERRORS=( "${ERRORS[@]}" "$NAME: Filesystems do not match" )
- echo $fsdiff | less
- fi
- popd > /dev/null
- done
- rm -R "$TEMPDIR"
- # check if everything was fine - if yes, exit clean+smooth
- if [ ${#ERRORS[*]} -eq 0 ]; then
- success "Everything OK, what a nice and lovely built firmware \o/"
- exit 0
- fi
- # got some errors - output them
- for errmsg in "${ERRORS[@]}"; do
- echo $errmsg
- done
- abort "Firmware check failed, see above :("
|