#!/bin/sh
# Update the root partition of a firmware image with
# the compiled sourcecode from an sdk.


usage () {
cat <<EOF
update_firmware - update the root partition of a firmware

This script updates the kernel and initrd root partition of a 
firmware image with OEM binaries built for that firmware. It is
usually shipped with a software SDK. The firmwarefile will
be changed permanently, so please back it up before using
this script.

USAGE:

update_firmware <firmwarefile> <final root password>

EOF
}

# check params
if [ $# -lt 1 ] ; then
    usage
    exit 1
fi

if ! [ -f "$1" ] ; then
    usage
    exit 1
fi

fw_file=$1

if [ $# = "2" ]; then
	passwd="$2"
else
	passwd="root"
fi

FINAL_DIR="$PWD/../install_root_final/"
TARGET_DIR="$PWD/target_root"
TAR_EXCLUDES="$PWD/tar-EXCLUDES"

# make a e2fs filesystem
dd if=/dev/zero of=root.initrd bs=1k count=10240
sudo /sbin/mke2fs -Fvm0 root.initrd 10240

# loop-mount root partition
mkdir -p "$TARGET_DIR"
sudo umount "$TARGET_DIR"
sudo mount -o loop -t ext2 root.initrd "$TARGET_DIR"

# create list of files that we do not want in the final firmware
rm -f "$TAR_EXCLUDES"
cd "$FINAL_DIR" && {
    find . -name "*.a" >> "$TAR_EXCLUDES" || exit 1
    find . -name "*.la" >> "$TAR_EXCLUDES" || exit 1
    find . -name "*.so" \
      -exec /bin/sh -c '(file -L {} | grep -q "shared object") || echo {}' \; \
      >> "$TAR_EXCLUDES" || exit 1
    sed -i 's,^\./,,' "$TAR_EXCLUDES" || exit 1
    cd -
} || exit 1
echo "./share" >> "$TAR_EXCLUDES"
echo "./include" >> "$TAR_EXCLUDES"
echo "./usr/include" >> "$TAR_EXCLUDES"
echo "./flashdisk/*" >> "$TAR_EXCLUDES"
echo ---- Excluding the following files ----
cat "$TAR_EXCLUDES"
echo ---------------------------------------

# copy install_root_final to TARGET_DIR
sudo tar -C "$FINAL_DIR" --exclude-from "$TAR_EXCLUDES" -cf - . | sudo tar -C "$TARGET_DIR" -xf -
[ "${PIPESTATUS[0]}" != "0" -o "${PIPESTATUS[1]}" != "0" ] && exit 1
rm -f "$TAR_EXCLUDES"

# replace passwd with user-supplied one
echo "Replacing root password with '$passwd'"
sudo ./cryptpasswd.pl -f "$TARGET_DIR/etc/passwd" -u "root" -p "$passwd"
if [ $? != "0" ]; then
	echo "Could not replace final password"
	exit 1;
fi

# unmount and repack initrd
sudo umount "$TARGET_DIR"

# convert root filesystem
echo Converting root filesystem
./data2img.sh root.initrd root.part
if [ $? != "0" ]; then
    echo "ERROR: Could not convert rootfs to root.part"
    rm -f root.part root.initrd replacepart_?_?
    rm -r "$TARGET_DIR"
    exit 1;
fi

# update root filesystem
echo Updating root filesystem
./replacepart.pl -p 0 -s 1 -a root.part $fw_file
if [ $? != "0" ]; then
    echo "ERROR: Could not update root filesystem"
    rm -f root.part root.initrd replacepart_?_?
    rm -r "$TARGET_DIR"
    exit 1;
fi

# update kernel image
echo Updating kernel image
./replacepart.pl -p 0 -s 0 -a zImage.bin $fw_file
if [ $? != "0" ]; then
    echo "ERROR: Could not update kernel image"
    rm -f root.part root.initrd replacepart_?_?
    rm -r "$TARGET_DIR"
    exit 1;
fi

rm -f root.part root.initrd replacepart_?_?

# cleanup
rm -r "$TARGET_DIR"

echo Firmware updated with local binaries
