#!/bin/bash -ex

# Copyright 2011 Ludovic Pouzenc <lpouzenc@gmail.com>

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

VERSION='1.0.0'

# Some tweakable parameters follows

# This script was tested upon Debian Squeeze and Debian Lenny
# You have to specify which one you use (yes I'm lazy)
DEBIAN_CODENAME=squeeze

# This is the path within all stuff will be downloaded, compiled, crunshed and so on 
BASEPATH=/root/tam3517

# This is the size of your SD card image. I've put 240 Mio (this IS small).
# No problem if image is smaller that real card (but you will not access at the extra space without resizing the last partition manually
# Big problems if you pickup a size bigger that your real card.
SD_SECTOR_COUNT=$((240*1024*2))

# End of tweakable parameters

# Some helpers for code factoring
function install_once() {
	last_update=$(stat -c%Y /var/lib/dpkg/info)
	now=$(date +%s)
	delta=$((now-last_update)) 
	[ $delta -lt 86400 ] || apt-get update

	while [ -n "$1" ] # Quotes are mandatory (WTF !!!)
	do
		state=$(dpkg -l $1 | tail -1)
		[ "${state:0:3}" = "ii " ] || apt-get -y install $1 
		shift
	done
}

function mkdir_once() {
	[ -d "$1" ] || mkdir -p "$1"
}

function wget_once() {
	[ -f "$2" ] || wget -O "$2" "$1"
}

# Begin of main code

# Env checks
[ $UID -eq 0 ] || ( echo "Must be run as root"; false )

# Add emdebian.org keys (used for their arm toolchain)
install_once emdebian-archive-keyring

# Add emdebian.org sources
if [ ! -f "/etc/apt/sources.list.d/emdebian.list" ]
then	echo "deb http://www.emdebian.org/debian/ squeeze main" > "/etc/apt/sources.list.d/emdebian.list"
	apt-get update
fi

# Install all necessary stuff for cross compiling and making up everything 
install_once coreutils build-essential tar rsync gcc-4.3-arm-linux-gnueabi

# Downloading of everything that is necessary
mkdir_once "$BASEPATH/dl"
wget_once "http://technexion.com/index.php/support-center/downloads/ti-cpu-modules/tam-3517/546-xuk-src-tar/download" "$BASEPATH/dl/xuk-src.tar.bz2"
wget_once "http://technexion.com/index.php/support-center/downloads/ti-cpu-modules/tam-3517/543-tam3517-sd-angstrom-img/download" "$BASEPATH/dl/tam3517-sd-angstrom.img.bz2" 
wget_once "http://www.pouzenc.fr/misc/bin/tam3517-rootfs-image-am3517-evm.tar.gz" "$BASEPATH/dl/tam3517-rootfs-image-am3517-evm.tar.gz"

# Envrionnement creation for target-system compilation
mkdir_once "$BASEPATH/crosscompil/xuk"
# x-loader, u-boot and kernel source extraction
[ -d "$BASEPATH/crosscompil/xuk/tam3517" ] || tar -xf "$BASEPATH/dl/xuk-src.tar.bz2" -C "$BASEPATH/crosscompil/xuk/"

# Cross-compilation
(
	# Some common env variable for cross compiling everything
	ARCH=arm
	CROSS_COMPILE=arm-linux-gnueabi-
	export ARCH CROSS_COMPILE

	# u-boot building (mainly for mkimage bin, used for uImage generation)
	if [ ! -x "$BASEPATH/crosscompil/xuk/tam3517/u-boot/tools/mkimage" ]
	then	cd "$BASEPATH/crosscompil/xuk/tam3517/u-boot"
		make tam3517_twister_config
		make
	fi
	# Check u-boot building result files
	[ -x "$BASEPATH/crosscompil/xuk/tam3517/u-boot/tools/mkimage" ]

	# Kernel building
	extra_path="$BASEPATH/crosscompil/xuk/tam3517/u-boot/tools:$PATH"
	cd "$BASEPATH/crosscompil/xuk/tam3517/kernel"
	[ -f ".config" ] || make tam3517_twister_defconfig
	[ -f "./arch/arm/boot/uImage" ] || make PATH="$extra_path" uImage modules

	# Compilation check for kernel
	[ -f "$BASEPATH/crosscompil/xuk/tam3517/kernel/arch/arm/boot/uImage" ]
)

# Preparing the generated SD image
mkdir_once "$BASEPATH/system/technexion/mount-loop/p2"
mkdir_once "$BASEPATH/system/from-narcissus/mount-loop/p1"
mkdir_once "$BASEPATH/system/from-narcissus/mount-loop/p2"

# Reuse of some part of the demo SD image from Technexion (boot partition with x-loader installed + technexion_tools folder)
[ -f "$BASEPATH/system/technexion/tam3517-sd-angstrom.img" ] || bzip2 -d -c "$BASEPATH/dl/tam3517-sd-angstrom.img.bz2" > "$BASEPATH/system/technexion/tam3517-sd-angstrom.img"

# Some offset computation for finding start of partitions in the Technexion demo image file
tech_p1_offset=$(fdisk -ul "$BASEPATH/system/technexion/tam3517-sd-angstrom.img" 2>/dev/null | sed -n 's/.*img1[^0-9]*\([0-9]\+\).*/\1/p')
tech_p2_offset=$(fdisk -ul "$BASEPATH/system/technexion/tam3517-sd-angstrom.img" 2>/dev/null | sed -n 's/.*img2[^0-9]*\([0-9]\+\).*/\1/p')

if [ ! -f "$BASEPATH/system/from-narcissus/tam3517-sd.img" ]; then
	# Boot partition sector-to-sector copy (includes a functionnal x-loader)
	dd if="$BASEPATH/system/technexion/tam3517-sd-angstrom.img" of="$BASEPATH/system/from-narcissus/tam3517-sd.img" count=$tech_p2_offset

	# MBR alteration for keeping only the first partition (boot partition)
	dd if=/dev/zero of="$BASEPATH/system/from-narcissus/tam3517-sd.img" bs=1 seek=464 count=32 conv=notrunc

	# Creating room space for the second partition (rootfs)
	dd if=/dev/zero of="$BASEPATH/system/from-narcissus/tam3517-sd.img" seek=$tech_p2_offset count=$((SD_SECTOR_COUNT-tech_p2_offset))

	# Creating the second partition (rootfs)
	echo -e "n\np\n2\n\n\np\nw\n" | fdisk -C $((SD_SECTOR_COUNT/255/63)) -H 255 -S 63 -b 512 "$BASEPATH/system/from-narcissus/tam3517-sd.img"

	# Formatting the newly created partition
	nar_p2_offset=$(fdisk -ul "$BASEPATH/system/from-narcissus/tam3517-sd.img" 2>/dev/null | sed -n 's/.*img2[^0-9]*\([0-9]\+\).*/\1/p')

	losetup -o $((nar_p2_offset*512)) -f "$BASEPATH/system/from-narcissus/tam3517-sd.img"
	nar_p2_loop_dev=$(losetup -j "$BASEPATH/system/from-narcissus/tam3517-sd.img" | cut -d ':' -f 1)
	mkfs.ext3 $nar_p2_loop_dev
	losetup -d $nar_p2_loop_dev	
fi

# Some offset computation and mount loop to work with demo and generated sd image
nar_p1_offset=$(fdisk -ul "$BASEPATH/system/from-narcissus/tam3517-sd.img" 2>/dev/null | sed -n 's/.*img1[^0-9]*\([0-9]\+\).*/\1/p')
nar_p2_offset=$(fdisk -ul "$BASEPATH/system/from-narcissus/tam3517-sd.img" 2>/dev/null | sed -n 's/.*img2[^0-9]*\([0-9]\+\).*/\1/p')

umount "$BASEPATH/system/technexion/mount-loop/p2" 2>/dev/null || true
mount -o loop,ro,offset=$((tech_p2_offset*512)) "$BASEPATH/system/technexion/tam3517-sd-angstrom.img" "$BASEPATH/system/technexion/mount-loop/p2"

umount "$BASEPATH/system/from-narcissus/mount-loop/p2" 2>/dev/null || true
mount -o loop,rw,offset=$((nar_p2_offset*512)) "$BASEPATH/system/from-narcissus/tam3517-sd.img" "$BASEPATH/system/from-narcissus/mount-loop/p2"

# rootfs construction
if [ ! -d "$BASEPATH/system/from-narcissus/mount-loop/p2/var" ]; then
	# Use narcissus generated rootfs as a base
	tar -xvf "$BASEPATH/dl/tam3517-rootfs-image-am3517-evm.tar.gz" -C "$BASEPATH/system/from-narcissus/mount-loop/p2/"

	# Add the technexion_tools folder from the demo image for flash-to-NAND stuff (without Android)
	rsync -ai --exclude 'technexion_tools/binary/android' --exclude 'technexion_tools/binary/angstrom/angstrom.tar.bz2' --exclude 'technexion_tools/binary/angstrom/modules.tar.bz2' "$BASEPATH/system/technexion/mount-loop/p2/technexion_tools" "$BASEPATH/system/from-narcissus/mount-loop/p2/"

	# Apply Technexion extra work above Angstrom (mainly for tuning hardware details)
	tar -xvf "$BASEPATH/system/technexion/mount-loop/p2/technexion_tools/binary/angstrom/extra.tar.bz2" -C "$BASEPATH/system/from-narcissus/mount-loop/p2/"

	# Replace their demo kernel for flash-to-nand
	cp -v "$BASEPATH/crosscompil/xuk/tam3517/kernel/arch/arm/boot/uImage" "$BASEPATH/system/from-narcissus/mount-loop/p2/technexion_tools/binary/angstrom/uImage"

	# Install our freshly built kernel modules
	(
		cd "$BASEPATH/crosscompil/xuk/tam3517/kernel"
		make INSTALL_MOD_PATH="$BASEPATH/system/from-narcissus/mount-loop/p2/" modules_install
	)

	# Build angstrom.tar.bz2 for flash-to-NAND
	tar -cj --exclude './technexion_tools' -f "$BASEPATH/system/from-narcissus/mount-loop/p2/technexion_tools/binary/angstrom/angstrom.tar.bz2" -C "$BASEPATH/system/from-narcissus/mount-loop/p2" .
	
	# TODO : modules.tar.bz2 ?
fi
	
umount "$BASEPATH/system/technexion/mount-loop/p2" 2>/dev/null || true
umount "$BASEPATH/system/from-narcissus/mount-loop/p2" 2>/dev/null || true

# Boot partition customization
umount "$BASEPATH/system/from-narcissus/mount-loop/p1" 2>/dev/null || true
mount -o loop,rw,offset=$((nar_p1_offset*512)) "$BASEPATH/system/from-narcissus/tam3517-sd.img" "$BASEPATH/system/from-narcissus/mount-loop/p1"
# Replace their demo kernel for SD card boot
cp -v "$BASEPATH/crosscompil/xuk/tam3517/kernel/arch/arm/boot/uImage" "$BASEPATH/system/from-narcissus/mount-loop/p1/boot/0/"
umount "$BASEPATH/system/from-narcissus/mount-loop/p1" 2>/dev/null || true

echo "Finished !!! If you can read this message, you have probably a correctly-generated SD card image at '$BASEPATH/system/from-narcissus/tam3517-sd.img'"