#!/bin/sh
#-
# $FreeWRT$
#-
# This file is part of the FreeWRT project. FreeWRT is copyrighted
# material, please see the LICENCE file in the top-level directory
# or at http://www.freewrt.org/licence for details.

# Copyright (c) Waldemar Brodkorb <wbx@freewrt.org>
# image builder script (version 0.2)

# change here the base variables
topdir=$(pwd)
basedir=/srv/apache2/downloads/1.0
toolsdir=${topdir}/staging_dir_mipsel/bin
scriptsdir=${topdir}/scripts
database=${topdir}/database/freewrt.db
usetmpfs=0

# do not change anything below

usage() {
	echo "Web Image Builder usage:"
	echo "Usage: `basename $0` -a <arch> -b <board> -k <kernelversion> -f <filesystem> -d <device> -o <outputfile> -p <packagelist>"
	echo "		-a cpu architecture, f.e. mipsel"
	echo "		-b board type, f.e. brcm"
	echo "		-k kernel version, 2.4 or 2.6"
	echo "		-f root filesystem type, f.e. jffs2"
	echo "		-d specific device, f.e. asus-wl500g"
	echo "		-p package list filename"
	echo "		-o output file for the firmware image"
	echo "Snapshot build usage:"
	echo "Usage: `basename $0` -s -n"
	echo "		-s build full snapshot"
	echo "		-n build snapshot without packages"
	exit 1
}

# snapshot mode
# it is good to start with "make distclean"
# to build a complete snapshot or release go into
# the menu and choose under "Package collection" -> All Packages
# save and exit, execute the script from TOPDIR
# sh scripts/ib.sh -s

snapshot() {
	kernel=2.4
	cd ${topdir}
	mkdir -p bin/packages
	mkdir -p bin/kernel
	mkdir -p bin/bootloader
	echo "starting full package build"
	rm .config
	make snapshotconfig
	make clean
	make
	for b in $allowed_boards;do
	  for d in $allowed_devices; do
	    for f in $allowed_fs; do
	    	B=$(echo $b|tr [:lower:] [:upper:])
		M=$(echo $d|tr [:lower:] [:upper:]| sed "s/-/_/g")
		echo "cleaning up first"
	    	make cleanbuild
	    	echo "compiling kernel for $d with filesystem $f"
	 	make subdir=target/linux/$b-$kernel compile-kernel FS=$f MODEL=$d BOARD=$b KERNEL=$kernel
		echo "creating base package for $d with filesystem $f"
		make package=base-files-arch install FS=$f MODEL=$d BOARD=$b KERNEL=$kernel FWRT_LINUX_2_4_${B}_${M}=y
		echo "copy kernel and loader"
		make subdir=target/image/brcm install-kernel install-loader FS=$f MODEL=$d BOARD=$b KERNEL=$kernel
	    done
	  done
	done
	exit 0
}

# check for needed applications
tools="mksquashfs-lzma trx addpattern mkfs.jffs2"

for t in ${tools}
  do 
   [ -x ${toolsdir}/${t} ] || echo "${t} application missing or not executable" 
done

[ -x ${scriptsdir}/ipkg ] || echo "ipkg application missing or not executable" 

# check for sqlite 
sqlite=$(which sqlite3)
[ -x ${sqlite} ] || "sqlite application is missing"

# simple sql functions
sql() {
	${sqlite} $database "select $1 from $2"
}
sqlw() {
	${sqlite} $database "select $1 from $2 where $3=\"$4\""
}

allowed_fs=$(sql name filesystems)
allowed_archs=$(sql name arches)
allowed_boards=$(sql name boards)
allowed_devices=$(sql name devices)
allowed_os_kernels=$(sql name os_kernels)

while getopts a:b:f:k:d:o:p:sn option
do
  case $option in
	a)
		archs=$OPTARG
		for a in $allowed_archs
		do
			if [ $archs = $a ]
			then
				arch=$a
			fi
		done
		if [ -z $arch ]
		  then
			echo "unsupported architecture: $archs"
			exit 1
		fi
		;;
	b)
		boards=$OPTARG
		for b in $allowed_boards
		do
			if [ $boards = $b ]
			then
				board=$b
			fi
		done
		if [ -z $board ]
		  then
			echo "unsupported board: $boards"
			exit 1
		fi
		;;
	f)
		filesystems=$OPTARG
		for f in $allowed_fs 
		  do
			if [ $filesystems = $f ]
			then 
				fs=$f
			fi
		done
		if [ -z $fs ]
		  then
			echo "unsupported filesystem: $filesystems"
			exit 1
		fi
		;;
	k)
		kernels=$OPTARG
		for k in $allowed_os_kernels
		  do
			if [ $kernels = $k ]
			then 
				kernel=$k
			fi
		done
		if [ -z $kernel ]
		  then
			echo "unsupported kernel version: $kernels"
			exit 1
		fi
		;;
	d)
		devices=$OPTARG
		for d in $allowed_devices
		  do
			if [ $devices = $d ]
			then 
				device=$d
			fi
		done
		if [ -z $device ]
		  then
			echo "unsupported device: $devices"
			exit 1
		fi
		;;
	o)
		outputfile=$OPTARG
		if [ -z $outputfile ] 
		then
			echo "You need to set an output file"
			exit 1
		fi
		;;
	p)
		packagelist=$OPTARG
		if [ -z $packagelist ] 
		then
			echo "You need to set a package list file"
			exit 1
		fi
		;;
	s)
		nopackages=0
		snapshot
		;;
	n)
		nopackages=1
		snapshot
		;;
 	*)
		echo "$0: unknown option: $option"
		usage
		exit 1
		;;
  esac
done

if [ -z $1 ]
  then
    usage
    exit 1
fi

if [ $usetmpfs = 1 ]
  then
   tmpdir=$(mktemp -d /dev/shm/fwrt.XXXXXX)
else
   tmpdir=$(mktemp -d)
fi
mkdir -p ${tmpdir}/tmp
mkdir -p ${tmpdir}/root
echo "creating temporary dir: ${tmpdir}"

echo -e "dest root /\noption offline_root ${tmpdir}/root" > ${tmpdir}/ipkg.conf
ipkg_command="env IPKG_TMP=${tmpdir}/tmp IPKG_INSTROOT=${tmpdir}/root IPKG_CONF_DIR=${tmpdir} ${scriptsdir}/ipkg -force-defaults -force-depends"

for p in $(grep -v '^#' $packagelist)
  do
	package_name=$(ls ${basedir}/${board}-${kernel}/packages/${p}_*)
	if [ -f "$package_name" ];
	  then
  		$ipkg_command install $(ls ${basedir}/${board}-${kernel}/packages/${p}_*)
	else
		echo "Package $p is missing in install directory"
		exit 127
	fi
done
# busybox + tmp hack
chmod 1777 ${tmpdir}/root/tmp
chmod 4755 ${tmpdir}/root/bin/busybox

erase_size=$(sqlw erase_size devices name ${device})

if [ $fs = "squashfs-symlinks" -o $fs = "squashfs-overlay" ]
  then 
	align=1024
else
	align=${erase_size}
fi

bootloader=${basedir}/${board}-${kernel}/boot/bootloader-${board}-${kernel}
kernelimg=${basedir}/${board}-${kernel}/kernel/kernel-${device}-${board}-${kernel}-${fs}

image_type=$(sqlw image_type devices name ${device})
image_opts=$(sqlw image_opts devices name ${device})
image_cmd=

case $image_type in 
	trx)
		image_command="${toolsdir}/trx ${image_opts} -o ${outputfile} ${bootloader}.gz ${kernelimg} -a ${align} ${tmpdir}/root.${fs}"
		;;
	addpattern)
		image_command="${toolsdir}/trx -o ${tmpdir}/${outputfile} ${bootloader}.gz ${kernelimg} -a ${align} ${tmpdir}/root.${fs}"
		image_cmd="${toolsdir}/addpattern ${image_opts} -i ${tmpdir}/${outputfile} -o ${outputfile} -g"
		;;
	elf)
		image_command="${toolsdir}/trx ${device_opts} -o ${tmpdir}/${outputfile} ${bootloader}.gz ${kernelimg} -a ${align} ${tmpdir}/root.${fs}"
		image_cmd="dd if=${bootloader}.elf of=${outputfile} bs=131072 conv=sync ; cat ${tmpdir}/${outputfile} >> ${outputfile}"
		;;
	*)
		echo "unknown image type: $image_type"
		exit 1
		;;
esac

jffs_opts="--little-endian --pad --squash-uid"
squashfs_opts="-le -nopad -noappend -root-owned"

case $fs in
	jffs2)
		fs_command="${toolsdir}/mkfs.jffs2 ${jffs_opts} -e ${erase_size} -o ${tmpdir}/root.${fs} -d ${tmpdir}/root"
		;;
	squashfs-*)
		fs_command="${toolsdir}/mksquashfs-lzma ${tmpdir}/root ${tmpdir}/root.${fs} ${squashfs_opts}"
		;;
esac

echo "create root filesystem image" 
$fs_command || echo "creating the root filesystem image failed"

echo "create firmware image"
$image_command || echo "failed to create firmware image (trx)"
$image_cmd || echo "failed to create firmware image (bin)"

[ -n $tmpdir ] && rm -rf $tmpdir
echo "successfully build firmware image: ${outputfile}"

